Today's the day. Renamed platform to framework.
This commit is contained in:
230
globalfunctions/AsciiConverter.cpp
Normal file
230
globalfunctions/AsciiConverter.cpp
Normal file
@ -0,0 +1,230 @@
|
||||
#include <framework/globalfunctions/AsciiConverter.h>
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
|
||||
template<typename T>
|
||||
ReturnValue_t AsciiConverter::scanAsciiDecimalNumber(const uint8_t** dataPtr,
|
||||
uint8_t len, T* value) {
|
||||
if (len > std::numeric_limits<T>().digits10) {
|
||||
return TOO_LONG_FOR_TARGET_TYPE;
|
||||
}
|
||||
|
||||
double temp;
|
||||
|
||||
ReturnValue_t result = scanAsciiDecimalNumber_(dataPtr, len, &temp);
|
||||
|
||||
*value = temp;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t AsciiConverter::scanAsciiHexByte(const uint8_t** dataPtr,
|
||||
uint8_t* value) {
|
||||
int8_t tmp;
|
||||
|
||||
tmp = convertHexChar(*dataPtr);
|
||||
(*dataPtr)++;
|
||||
if (tmp == -1) {
|
||||
return INVALID_CHARACTERS;
|
||||
}
|
||||
if (tmp == -2) {
|
||||
tmp = 0;
|
||||
}
|
||||
|
||||
*value = tmp << 4;
|
||||
|
||||
tmp = convertHexChar(*dataPtr);
|
||||
(*dataPtr)++;
|
||||
if (tmp == -1) {
|
||||
return INVALID_CHARACTERS;
|
||||
}
|
||||
if (tmp != -2) {
|
||||
*value += tmp;
|
||||
} else {
|
||||
*value = *value >> 4;
|
||||
}
|
||||
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t AsciiConverter::scanAsciiDecimalNumber_(uint8_t const ** dataPtr,
|
||||
uint8_t len, double* value) {
|
||||
|
||||
uint8_t const *ptr = *dataPtr;
|
||||
int8_t sign = 1;
|
||||
float decimal = 0;
|
||||
bool abort = false;
|
||||
|
||||
*value = 0;
|
||||
|
||||
//ignore leading space
|
||||
ptr = clearSpace(ptr, len);
|
||||
|
||||
while ((ptr - *dataPtr < len) && !abort) {
|
||||
switch (*ptr) {
|
||||
case '+':
|
||||
sign = 1;
|
||||
break;
|
||||
case '-':
|
||||
sign = -1;
|
||||
break;
|
||||
case '.':
|
||||
decimal = 1;
|
||||
break;
|
||||
case ' ':
|
||||
case 0x0d:
|
||||
case 0x0a:
|
||||
//ignore trailing space
|
||||
ptr = clearSpace(ptr, len - (ptr - *dataPtr)) - 1; //before aborting the loop, ptr will be incremented
|
||||
abort = true;
|
||||
break;
|
||||
default:
|
||||
if ((*ptr < 0x30) || (*ptr > 0x39)) {
|
||||
return INVALID_CHARACTERS;
|
||||
}
|
||||
*value = *value * 10 + (*ptr - 0x30);
|
||||
if (decimal > 0) {
|
||||
decimal *= 10;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if (decimal == 0) {
|
||||
decimal = 1;
|
||||
}
|
||||
|
||||
*value = *value / (decimal) * sign;
|
||||
|
||||
*dataPtr = ptr;
|
||||
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t AsciiConverter::printFloat(uint8_t* buffer, uint32_t bufferLength,
|
||||
float value, uint8_t decimalPlaces, uint32_t *printedSize) {
|
||||
*printedSize = 0;
|
||||
uint32_t streamposition = 0, integerSize;
|
||||
bool negative = (value < 0);
|
||||
int32_t digits = bufferLength - decimalPlaces - 1;
|
||||
if (digits <= 0) {
|
||||
return BUFFER_TOO_SMALL;
|
||||
}
|
||||
if (negative) {
|
||||
digits -= 1;
|
||||
buffer[streamposition++] = '-';
|
||||
value = -value;
|
||||
}
|
||||
float maximumNumber = pow(10, digits);
|
||||
if (value >= maximumNumber) {
|
||||
return BUFFER_TOO_SMALL;
|
||||
}
|
||||
//print the numbers before the decimal point;
|
||||
ReturnValue_t result = printInteger(buffer + streamposition,
|
||||
bufferLength - streamposition - decimalPlaces - 1, value,
|
||||
&integerSize);
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
streamposition += integerSize;
|
||||
//The decimal Point
|
||||
buffer[streamposition++] = '.';
|
||||
|
||||
//Print the decimals
|
||||
uint32_t integerValue = value;
|
||||
value -= integerValue;
|
||||
value = value * pow(10, decimalPlaces);
|
||||
result = printInteger(buffer + streamposition, decimalPlaces, round(value),
|
||||
&integerSize, true);
|
||||
*printedSize = integerSize + streamposition;
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t AsciiConverter::printInteger(uint8_t* buffer,
|
||||
uint32_t bufferLength, uint32_t value, uint32_t *printedSize,
|
||||
bool leadingZeros) {
|
||||
*printedSize = 0;
|
||||
if (bufferLength == 0) {
|
||||
return BUFFER_TOO_SMALL;
|
||||
}
|
||||
uint32_t maximumNumber = -1;
|
||||
if (bufferLength < 10) {
|
||||
maximumNumber = pow(10, bufferLength);
|
||||
if (value >= maximumNumber) {
|
||||
return BUFFER_TOO_SMALL;
|
||||
}
|
||||
maximumNumber /= 10;
|
||||
} else {
|
||||
if (!(value <= maximumNumber)) {
|
||||
return BUFFER_TOO_SMALL;
|
||||
}
|
||||
maximumNumber = 1000000000;
|
||||
}
|
||||
if (!leadingZeros && (value == 0)) {
|
||||
buffer[(*printedSize)++] = '0';
|
||||
return RETURN_OK;
|
||||
}
|
||||
while (maximumNumber >= 1) {
|
||||
uint8_t number = value / maximumNumber;
|
||||
value = value - (number * maximumNumber);
|
||||
if (!leadingZeros && number == 0) {
|
||||
maximumNumber /= 10;
|
||||
} else {
|
||||
leadingZeros = true;
|
||||
buffer[(*printedSize)++] = '0' + number;
|
||||
maximumNumber /= 10;
|
||||
}
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t AsciiConverter::printSignedInteger(uint8_t* buffer,
|
||||
uint32_t bufferLength, int32_t value, uint32_t *printedSize) {
|
||||
bool negative = false;
|
||||
if ((bufferLength > 0) && (value < 0)) {
|
||||
*buffer++ = '-';
|
||||
bufferLength--;
|
||||
value = -value;
|
||||
negative = true;
|
||||
}
|
||||
ReturnValue_t result = printInteger(buffer, bufferLength, value,
|
||||
printedSize);
|
||||
if (negative) {
|
||||
(*printedSize)++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int8_t AsciiConverter::convertHexChar(const uint8_t* character) {
|
||||
if ((*character > 0x60) && (*character < 0x67)) {
|
||||
return *character - 0x61 + 10;
|
||||
} else if ((*character > 0x40) && (*character < 0x47)) {
|
||||
return *character - 0x41 + 10;
|
||||
} else if ((*character > 0x2F) && (*character < 0x3A)) {
|
||||
return *character - 0x30;
|
||||
} else if (*character == ' ') {
|
||||
return -2;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
template ReturnValue_t AsciiConverter::scanAsciiDecimalNumber<float>(
|
||||
const uint8_t** dataPtr, uint8_t len, float* value);
|
||||
template ReturnValue_t AsciiConverter::scanAsciiDecimalNumber<uint8_t>(
|
||||
const uint8_t** dataPtr, uint8_t len, uint8_t* value);
|
||||
template ReturnValue_t AsciiConverter::scanAsciiDecimalNumber<uint16_t>(
|
||||
const uint8_t** dataPtr, uint8_t len, uint16_t* value);
|
||||
template ReturnValue_t AsciiConverter::scanAsciiDecimalNumber<double>(
|
||||
const uint8_t** dataPtr, uint8_t len, double* value);
|
||||
|
||||
const uint8_t* AsciiConverter::clearSpace(const uint8_t* data, uint8_t len) {
|
||||
while (len > 0) {
|
||||
if ((*data != ' ') && (*data != 0x0a) && (*data != 0x0d)) {
|
||||
return data;
|
||||
}
|
||||
data++;
|
||||
len--;
|
||||
}
|
||||
return data;
|
||||
}
|
Reference in New Issue
Block a user