unified parsing of numeric values, documentation
This commit is contained in:
+49
-42
@@ -100,6 +100,31 @@ static const char* dayNames[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
|
|||||||
#define NULL_VALUE "-"
|
#define NULL_VALUE "-"
|
||||||
#define MAX_POS 16
|
#define MAX_POS 16
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Parse an unsigned int value.
|
||||||
|
* @param str the string to parse.
|
||||||
|
* @param base the numerical base.
|
||||||
|
* @param minValue the minimum resulting value.
|
||||||
|
* @param maxValue the maximum resulting value.
|
||||||
|
* @param result the variable in which to store an error code when parsing failed or the value is out of bounds.
|
||||||
|
*/
|
||||||
|
unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue, result_t& result) {
|
||||||
|
char* strEnd = NULL;
|
||||||
|
|
||||||
|
unsigned int ret = strtoul(str, &strEnd, base);
|
||||||
|
|
||||||
|
if (strEnd == NULL || *strEnd != 0) {
|
||||||
|
result = RESULT_ERR_INVALID_ARG; // invalid value
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret < minValue || ret > maxValue) {
|
||||||
|
result = RESULT_ERR_INVALID_ARG; // invalid value
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
result_t DataField::create(std::vector<std::string>::iterator& it,
|
result_t DataField::create(std::vector<std::string>::iterator& it,
|
||||||
const std::vector<std::string>::iterator end,
|
const std::vector<std::string>::iterator end,
|
||||||
const std::map< std::string, DataField*> templates,
|
const std::map< std::string, DataField*> templates,
|
||||||
@@ -168,18 +193,9 @@ result_t DataField::create(std::vector<std::string>::iterator& it,
|
|||||||
if (++offsetCnt > 2)
|
if (++offsetCnt > 2)
|
||||||
return RESULT_ERR_INVALID_ARG; //invalid pos definition
|
return RESULT_ERR_INVALID_ARG; //invalid pos definition
|
||||||
|
|
||||||
const char* start = token.c_str();
|
unsigned int pos = parseInt(token.c_str(), 10, 1, MAX_POS + 1, result) - 1; // input is 1-based
|
||||||
char* end = NULL;
|
if (result != RESULT_OK)
|
||||||
unsigned int pos = strtoul(start, &end, 10) - 1; // 1-based
|
|
||||||
if (end != start + strlen(start)) {
|
|
||||||
result = RESULT_ERR_INVALID_ARG; // invalid pos definition
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
if (pos > MAX_POS) {
|
|
||||||
result = RESULT_ERR_INVALID_ARG; // invalid pos definition
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offsetCnt == 1)
|
if (offsetCnt == 1)
|
||||||
offset = pos;
|
offset = pos;
|
||||||
@@ -204,26 +220,22 @@ result_t DataField::create(std::vector<std::string>::iterator& it,
|
|||||||
std::string divisorStr = *it++;
|
std::string divisorStr = *it++;
|
||||||
if (divisorStr.empty() == false) {
|
if (divisorStr.empty() == false) {
|
||||||
if (divisorStr.find_first_not_of("0123456789") == std::string::npos) {
|
if (divisorStr.find_first_not_of("0123456789") == std::string::npos) {
|
||||||
const char* start = divisorStr.c_str();
|
divisor = parseInt(divisorStr.c_str(), 10, 1, 10000, result);
|
||||||
char* end = NULL;
|
if (result != RESULT_OK)
|
||||||
divisor = strtoul(start, &end, 10);
|
|
||||||
if (end != start + strlen(start)) {
|
|
||||||
result = RESULT_ERR_INVALID_ARG;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
std::istringstream stream(divisorStr);
|
std::istringstream stream(divisorStr);
|
||||||
while (std::getline(stream, token, VALUE_SEPARATOR) != 0) {
|
while (std::getline(stream, token, VALUE_SEPARATOR) != 0) {
|
||||||
const char* start = token.c_str();
|
const char* str = token.c_str();
|
||||||
char* end = NULL;
|
char* strEnd = NULL;
|
||||||
unsigned int id = strtoul(start, &end, 10);
|
unsigned int id = strtoul(str, &strEnd, 10);
|
||||||
if (end == NULL || end == start || *end != '=') {
|
if (strEnd == NULL || strEnd == str || *strEnd != '=') {
|
||||||
result = RESULT_ERR_INVALID_ARG;
|
result = RESULT_ERR_INVALID_ARG;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
values[id] = std::string(end + 1);
|
values[id] = std::string(strEnd + 1);
|
||||||
}
|
}
|
||||||
if (result != RESULT_OK)
|
if (result != RESULT_OK)
|
||||||
break;
|
break;
|
||||||
@@ -524,6 +536,7 @@ result_t StringDataField::writeSymbols(std::istringstream& input,
|
|||||||
incr = -1;
|
incr = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result_t result;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (size_t offset = start; offset != end; offset += incr, i++) {
|
for (size_t offset = start; offset != end; offset += incr, i++) {
|
||||||
switch (m_dataType.type)
|
switch (m_dataType.type)
|
||||||
@@ -542,11 +555,10 @@ result_t StringDataField::writeSymbols(std::istringstream& input,
|
|||||||
if (input.eof() == true)
|
if (input.eof() == true)
|
||||||
return RESULT_ERR_INVALID_ARG; // invalid hex value
|
return RESULT_ERR_INVALID_ARG; // invalid hex value
|
||||||
|
|
||||||
str = token.c_str();
|
result_t result;
|
||||||
strEnd = NULL;
|
value = parseInt(token.c_str(), 16, 0, 0xff, result);
|
||||||
value = strtoul(str, &strEnd, 16);
|
if (result != RESULT_OK)
|
||||||
if (strEnd != str + strlen(str))
|
return result; // invalid hex value
|
||||||
return RESULT_ERR_INVALID_ARG; // invalid hex value
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case bt_dat:
|
case bt_dat:
|
||||||
@@ -554,11 +566,9 @@ result_t StringDataField::writeSymbols(std::istringstream& input,
|
|||||||
continue; // skip weekday in between
|
continue; // skip weekday in between
|
||||||
if (std::getline(input, token, '.') == 0)
|
if (std::getline(input, token, '.') == 0)
|
||||||
return RESULT_ERR_INVALID_ARG; // incomplete
|
return RESULT_ERR_INVALID_ARG; // incomplete
|
||||||
str = token.c_str();
|
value = parseInt(token.c_str(), 10, 0, 9999, result);
|
||||||
strEnd = NULL;
|
if (result != RESULT_OK)
|
||||||
value = strtoul(str, &strEnd, 10);
|
return result; // invalid date part
|
||||||
if (strEnd != str + strlen(str))
|
|
||||||
return RESULT_ERR_INVALID_ARG; // invalid date part
|
|
||||||
if (i + 1 == m_length && value >= 2000)
|
if (i + 1 == m_length && value >= 2000)
|
||||||
value -= 2000;
|
value -= 2000;
|
||||||
else if (value < 1 || (i == 0 && value > 31) || (i == 1 && value > 12))
|
else if (value < 1 || (i == 0 && value > 31) || (i == 1 && value > 12))
|
||||||
@@ -567,12 +577,10 @@ result_t StringDataField::writeSymbols(std::istringstream& input,
|
|||||||
case bt_tim:
|
case bt_tim:
|
||||||
if (std::getline(input, token, ':') == 0)
|
if (std::getline(input, token, ':') == 0)
|
||||||
return RESULT_ERR_INVALID_ARG; // incomplete
|
return RESULT_ERR_INVALID_ARG; // incomplete
|
||||||
str = token.c_str();
|
value = parseInt(token.c_str(), 10, 0, 59, result);
|
||||||
strEnd = NULL;
|
if (result != RESULT_OK)
|
||||||
value = strtoul(str, &strEnd, 10);
|
return result; // invalid time part
|
||||||
if (strEnd != str + strlen(str))
|
if ((i == 0 && value > 24) || (i > 0 && ( last == 24 && value > 0) ))
|
||||||
return RESULT_ERR_INVALID_ARG; // invalid time part
|
|
||||||
if ((i == 0 && value > 24) || (i > 0 && (value > 59 || ( last == 24 && value > 0) )))
|
|
||||||
return RESULT_ERR_INVALID_ARG; // invalid time part
|
return RESULT_ERR_INVALID_ARG; // invalid time part
|
||||||
if (m_length == 1) { // truncated time
|
if (m_length == 1) { // truncated time
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
@@ -775,11 +783,10 @@ result_t NumberDataField::writeSymbols(std::istringstream& input,
|
|||||||
unsigned int value;
|
unsigned int value;
|
||||||
|
|
||||||
const char* str = input.str().c_str();
|
const char* str = input.str().c_str();
|
||||||
size_t len = strlen(str);
|
|
||||||
if (strcasecmp(str, NULL_VALUE) == 0)
|
if (strcasecmp(str, NULL_VALUE) == 0)
|
||||||
// replacement value
|
// replacement value
|
||||||
value = m_dataType.replacement;
|
value = m_dataType.replacement;
|
||||||
else if (len == 0)
|
else if (str == NULL || *str == 0)
|
||||||
return RESULT_ERR_INVALID_ARG; // input too short
|
return RESULT_ERR_INVALID_ARG; // input too short
|
||||||
else {
|
else {
|
||||||
char* strEnd = NULL;
|
char* strEnd = NULL;
|
||||||
@@ -793,13 +800,13 @@ result_t NumberDataField::writeSymbols(std::istringstream& input,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
value = strtoul(str, &strEnd, 10);
|
value = strtoul(str, &strEnd, 10);
|
||||||
if (strEnd != str + len)
|
if (strEnd == NULL || *strEnd != 0)
|
||||||
return RESULT_ERR_INVALID_ARG; // invalid value
|
return RESULT_ERR_INVALID_ARG; // invalid value
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
char* strEnd = NULL;
|
char* strEnd = NULL;
|
||||||
double dvalue = strtod(str, &strEnd);
|
double dvalue = strtod(str, &strEnd);
|
||||||
if (strEnd != str + len)
|
if (strEnd == NULL || strEnd != 0)
|
||||||
return RESULT_ERR_INVALID_ARG; // invalid value
|
return RESULT_ERR_INVALID_ARG; // invalid value
|
||||||
dvalue = round(dvalue * m_divisor);
|
dvalue = round(dvalue * m_divisor);
|
||||||
if ((m_dataType.flags & SIG) != 0) {
|
if ((m_dataType.flags & SIG) != 0) {
|
||||||
|
|||||||
+2
-2
@@ -88,11 +88,11 @@ public:
|
|||||||
* @brief Factory method for creating new instances.
|
* @brief Factory method for creating new instances.
|
||||||
* @param it the iterator to traverse for the definition parts.
|
* @param it the iterator to traverse for the definition parts.
|
||||||
* @param end the iterator pointing to the end of the definition parts.
|
* @param end the iterator pointing to the end of the definition parts.
|
||||||
* @param templates a map of DataField templates to be referenced by name.
|
* @param templates a map of @a DataField templates to be referenced by name.
|
||||||
* @param returnField the variable in which to store the created instance.
|
* @param returnField the variable in which to store the created instance.
|
||||||
* @param isSetMessage whether the field is part of a set message (default false).
|
* @param isSetMessage whether the field is part of a set message (default false).
|
||||||
* @param dstAddress the destination bus address (default @a SYN for creating a template @a DataField).
|
* @param dstAddress the destination bus address (default @a SYN for creating a template @a DataField).
|
||||||
* @return @a RESULT_OK on success, @a RESULT_ERR_EOF if the iterator is empty, or an error code.
|
* @return @a RESULT_OK on success, or an error code.
|
||||||
* Note: the caller needs to free the created instance.
|
* Note: the caller needs to free the created instance.
|
||||||
*/
|
*/
|
||||||
static result_t create(std::vector<std::string>::iterator& it, const std::vector<std::string>::iterator end,
|
static result_t create(std::vector<std::string>::iterator& it, const std::vector<std::string>::iterator end,
|
||||||
|
|||||||
Reference in New Issue
Block a user