User defined decimal separator for values

Partially solves #1161
This commit is contained in:
Edward Firmo
2024-02-27 10:32:06 +01:00
parent 89876fdfcf
commit d5f5a3eaaf
6 changed files with 1000 additions and 38 deletions

View File

@@ -1,6 +1,8 @@
// text.h
#pragma once
#include <algorithm>
#include <cctype>
#include <cstring>
#include <string>
@@ -34,15 +36,65 @@ namespace nspanel_ha_blueprint {
* Note: The destination array is always null-terminated, even if the source string
* is truncated to fit into the array.
*/
template<size_t N>
template <unsigned int N>
void copyStringToCharArray(char (&dest)[N], const std::string& src) {
static_assert(N > 0, "Destination array size must be greater than 0.");
// Ensure we do not exceed the buffer size, leaving space for the null terminator
size_t length = std::min(src.size(), N - 1);
// Copy up to N - 1 characters to ensure there's room for the null terminator
std::strncpy(dest, src.c_str(), N - 1);
// Copy the string data into the destination buffer
std::strncpy(dest, src.c_str(), length);
// Manually null-terminate the destination array
dest[N - 1] = '\0';
// Explicitly null-terminate the destination buffer
dest[length] = '\0';
}
// Helper function to determine if a character is part of a number
bool isNumberChar(char c) {
return std::isdigit(c) || c == '.' || c == '-' || c == ',';
}
/**
* Adjusts the decimal separator in a numeric string to a specified character.
* This function identifies and modifies the decimal separator of a number within a string,
* ensuring that only the first occurrence is replaced if it is a valid number followed by
* any non-numeric characters (e.g., units of measurement). If the input string does not
* start with a valid number, it is returned unchanged.
*
* @param input The string potentially containing a numeric value followed by text.
* @param decimalSeparator The character to use as the decimal separator.
* @return A string with the decimal separator adjusted if the input is a valid number,
* otherwise the original input string.
*/
std::string adjustDecimalSeparator(const std::string& input, char decimalSeparator) {
// Immediately return the original string if the desired decimal separator is "."
if (decimalSeparator == '.') {
return input;
}
// Find the end of the numeric part of the string
size_t numericEnd = 0;
for (; numericEnd < input.size() && isNumberChar(input[numericEnd]); ++numericEnd);
// Extract the numeric part and the suffix (if any)
std::string numericPart = input.substr(0, numericEnd);
std::string suffix = input.substr(numericEnd);
// Attempt to convert the numeric part to a double
char* end;
double val = strtod(numericPart.c_str(), &end);
// Check if conversion was successful (end points to a null terminator if so)
if (end != numericPart.c_str() && *end == '\0') {
// Find and replace only the first occurrence of '.' with the specified decimalSeparator
size_t decimalPointPos = numericPart.find('.');
if (decimalPointPos != std::string::npos) {
numericPart[decimalPointPos] = decimalSeparator;
}
return numericPart + suffix;
} else {
// If the input is not a number, return it as is
return input;
}
}
} // namespace nspanel_ha_blueprint