From deae06da9f6a9b99b20d33d0111c8f358e38f1a8 Mon Sep 17 00:00:00 2001 From: Jan Breuer <jan.breuer@jaybee.cz> Date: 周一, 10 8月 2015 20:08:37 +0800 Subject: [PATCH] Resolve #39: Correct handling of unsigned integers --- libscpi/src/parser.c | 54 ++++++++++++++++++++++---- libscpi/test/test_scpi_utils.c | 26 +++++++++++++ libscpi/src/utils_private.h | 1 libscpi/inc/scpi/parser.h | 2 + libscpi/test/test_parser.c | 1 libscpi/src/utils.c | 13 ++++++ 6 files changed, 88 insertions(+), 9 deletions(-) diff --git a/libscpi/inc/scpi/parser.h b/libscpi/inc/scpi/parser.h index 4bb8d2c..2402c85 100644 --- a/libscpi/inc/scpi/parser.h +++ b/libscpi/inc/scpi/parser.h @@ -61,12 +61,14 @@ scpi_bool_t SCPI_Parameter(scpi_t * context, scpi_parameter_t * parameter, scpi_bool_t mandatory); scpi_bool_t SCPI_ParamIsNumber(scpi_parameter_t * parameter, scpi_bool_t suffixAllowed); scpi_bool_t SCPI_ParamToInt(scpi_t * context, scpi_parameter_t * parameter, int32_t * value); + scpi_bool_t SCPI_ParamToUnsignedInt(scpi_t * context, scpi_parameter_t * parameter, uint32_t * value); scpi_bool_t SCPI_ParamToDouble(scpi_t * context, scpi_parameter_t * parameter, double * value); scpi_bool_t SCPI_ParamToChoice(scpi_t * context, scpi_parameter_t * parameter, const scpi_choice_def_t * options, int32_t * value); scpi_bool_t SCPI_ChoiceToName(const scpi_choice_def_t * options, int32_t tag, const char ** text); scpi_bool_t SCPI_ParamInt(scpi_t * context, int32_t * value, scpi_bool_t mandatory); + scpi_bool_t SCPI_ParamUnsignedInt(scpi_t * context, uint32_t * value, scpi_bool_t mandatory); scpi_bool_t SCPI_ParamDouble(scpi_t * context, double * value, scpi_bool_t mandatory); scpi_bool_t SCPI_ParamCharacters(scpi_t * context, const char ** value, size_t * len, scpi_bool_t mandatory); scpi_bool_t SCPI_ParamArbitraryBlock(scpi_t * context, const char ** value, size_t * len, scpi_bool_t mandatory); diff --git a/libscpi/src/parser.c b/libscpi/src/parser.c index dfe84d7..3475265 100644 --- a/libscpi/src/parser.c +++ b/libscpi/src/parser.c @@ -532,7 +532,7 @@ * @param value result * @return TRUE if succesful */ -scpi_bool_t SCPI_ParamToInt(scpi_t * context, scpi_parameter_t * parameter, int32_t * value) { +static scpi_bool_t ParamToInt(scpi_t * context, scpi_parameter_t * parameter, int32_t * value, scpi_bool_t sign) { if (!value) { SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); @@ -541,16 +541,43 @@ switch (parameter->type) { case SCPI_TOKEN_HEXNUM: - return strToLong(parameter->ptr, value, 16) > 0 ? TRUE : FALSE; + return strToULong(parameter->ptr, (uint32_t *)value, 16) > 0 ? TRUE : FALSE; case SCPI_TOKEN_OCTNUM: - return strToLong(parameter->ptr, value, 8) > 0 ? TRUE : FALSE; + return strToULong(parameter->ptr, (uint32_t *)value, 8) > 0 ? TRUE : FALSE; case SCPI_TOKEN_BINNUM: - return strToLong(parameter->ptr, value, 2) > 0 ? TRUE : FALSE; + return strToULong(parameter->ptr, (uint32_t *)value, 2) > 0 ? TRUE : FALSE; case SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA: case SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA_WITH_SUFFIX: - return strToLong(parameter->ptr, value, 10) > 0 ? TRUE : FALSE; + if (sign) { + return strToLong(parameter->ptr, value, 10) > 0 ? TRUE : FALSE; + } else { + return strToULong(parameter->ptr, (uint32_t *)value, 10) > 0 ? TRUE : FALSE; + } } return FALSE; +} + + +/** + * Convert parameter to integer + * @param context + * @param parameter + * @param value result + * @return TRUE if succesful + */ +scpi_bool_t SCPI_ParamToInt(scpi_t * context, scpi_parameter_t * parameter, int32_t * value) { + return ParamToInt(context, parameter, value, TRUE); +} + +/** + * Convert parameter to unsigned integer + * @param context + * @param parameter + * @param value result + * @return TRUE if succesful + */ +scpi_bool_t SCPI_ParamToUnsignedInt(scpi_t * context, scpi_parameter_t * parameter, uint32_t * value) { + return ParamToInt(context, parameter, (int32_t *)value, FALSE); } /** @@ -560,9 +587,10 @@ * @param value result * @return TRUE if succesful */ +#include "stdio.h" scpi_bool_t SCPI_ParamToDouble(scpi_t * context, scpi_parameter_t * parameter, double * value) { scpi_bool_t result = FALSE; - int32_t valint; + uint32_t valint; if (!value) { SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); @@ -573,7 +601,7 @@ case SCPI_TOKEN_HEXNUM: case SCPI_TOKEN_OCTNUM: case SCPI_TOKEN_BINNUM: - result = SCPI_ParamToInt(context, parameter, &valint); + result = SCPI_ParamToUnsignedInt(context, parameter, &valint); *value = valint; break; case SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA: @@ -622,7 +650,7 @@ * @param mandatory * @return */ -scpi_bool_t SCPI_ParamInt(scpi_t * context, int32_t * value, scpi_bool_t mandatory) { +static scpi_bool_t ParamInt(scpi_t * context, int32_t * value, scpi_bool_t mandatory, scpi_bool_t sign) { scpi_bool_t result; scpi_parameter_t param; @@ -634,7 +662,7 @@ result = SCPI_Parameter(context, ¶m, mandatory); if (result) { if (SCPI_ParamIsNumber(¶m, FALSE)) { - SCPI_ParamToInt(context, ¶m, value); + result = ParamToInt(context, ¶m, value, sign); } else if (SCPI_ParamIsNumber(¶m, TRUE)) { SCPI_ErrorPush(context, SCPI_ERROR_SUFFIX_NOT_ALLOWED); result = FALSE; @@ -646,6 +674,14 @@ return result; } +scpi_bool_t SCPI_ParamInt(scpi_t * context, int32_t * value, scpi_bool_t mandatory) { + return ParamInt(context, value, mandatory, TRUE); +} + +scpi_bool_t SCPI_ParamUnsignedInt(scpi_t * context, uint32_t * value, scpi_bool_t mandatory) { + return ParamInt(context, (int32_t *)value, mandatory, FALSE); +} + /** * Read character parameter * @param context diff --git a/libscpi/src/utils.c b/libscpi/src/utils.c index 0a9de65..66dbc64 100644 --- a/libscpi/src/utils.c +++ b/libscpi/src/utils.c @@ -156,6 +156,19 @@ } /** + * Converts string to unsigned 32bit integer representation + * @param str string value + * @param val 32bit integer result + * @return number of bytes used in string + */ +size_t strToULong(const char * str, uint32_t * val, int8_t base) { + char * endptr; + *val = strtoul(str, &endptr, base); + return endptr - str; +} + + +/** * Converts string to double representation * @param str string value * @param val double result diff --git a/libscpi/src/utils_private.h b/libscpi/src/utils_private.h index aefdf8f..473a98f 100644 --- a/libscpi/src/utils_private.h +++ b/libscpi/src/utils_private.h @@ -55,6 +55,7 @@ scpi_bool_t compareStr(const char * str1, size_t len1, const char * str2, size_t len2) LOCAL; scpi_bool_t compareStrAndNum(const char * str1, size_t len1, const char * str2, size_t len2, int32_t * num) LOCAL; size_t strToLong(const char * str, int32_t * val, int8_t base) LOCAL; + size_t strToULong(const char * str, uint32_t * val, int8_t base) LOCAL; size_t strToDouble(const char * str, double * val) LOCAL; scpi_bool_t locateText(const char * str1, size_t len1, const char ** str2, size_t * len2) LOCAL; scpi_bool_t locateStr(const char * str1, size_t len1, const char ** str2, size_t * len2) LOCAL; diff --git a/libscpi/test/test_parser.c b/libscpi/test/test_parser.c index 84761c5..4b3111d 100644 --- a/libscpi/test/test_parser.c +++ b/libscpi/test/test_parser.c @@ -367,6 +367,7 @@ TEST_ParamDouble("#B101010", TRUE, 42, TRUE, 0); TEST_ParamDouble("#H101010", TRUE, 1052688, TRUE, 0); TEST_ParamDouble("#Q10", TRUE, 8, TRUE, 0); + TEST_ParamDouble("#HFFFFFFFF", TRUE, 0xFFFFFFFFu, TRUE, 0); TEST_ParamDouble("", TRUE, 0, FALSE, -109); // missing parameter TEST_ParamDouble("abcd", TRUE, 0, FALSE, -104); // Data type error diff --git a/libscpi/test/test_scpi_utils.c b/libscpi/test/test_scpi_utils.c index af5aadf..dd3bfcc 100644 --- a/libscpi/test/test_scpi_utils.c +++ b/libscpi/test/test_scpi_utils.c @@ -142,6 +142,31 @@ TEST_STR_TO_LONG("18", 1, 1, 8); // octal 1, 8 is ignored } +static void test_strToULong() { + size_t result; + uint32_t val; + +#define TEST_STR_TO_ULONG(s, r, v, b) \ + do { \ + result = strToULong(s, &val, b); \ + CU_ASSERT_EQUAL(val, v); \ + CU_ASSERT_EQUAL(result, r); \ + } while(0) \ + + TEST_STR_TO_LONG("", 0, 0, 10); + TEST_STR_TO_LONG("1", 1, 1, 10); + TEST_STR_TO_LONG("10", 2, 10, 10); + TEST_STR_TO_LONG("100MHz", 3, 100, 10); + TEST_STR_TO_LONG("MHz", 0, 0, 10); + TEST_STR_TO_LONG("1.4", 1, 1, 10); + TEST_STR_TO_LONG(" 1", 2, 1, 10); + TEST_STR_TO_LONG(" +100", 5, 100, 10); // space and + + TEST_STR_TO_LONG("FF", 2, 255, 16); // hexadecimal FF + TEST_STR_TO_LONG("77", 2, 63, 8); // octal 77 + TEST_STR_TO_LONG("18", 1, 1, 8); // octal 1, 8 is ignored + TEST_STR_TO_LONG("FFFFFFFF", 8, 0xffffffffu, 16); // octal 1, 8 is ignored +} + static void test_strToDouble() { double val; size_t result; @@ -458,6 +483,7 @@ || (NULL == CU_add_test(pSuite, "longToStr", test_longToStr)) || (NULL == CU_add_test(pSuite, "doubleToStr", test_doubleToStr)) || (NULL == CU_add_test(pSuite, "strToLong", test_strToLong)) + || (NULL == CU_add_test(pSuite, "strToULong", test_strToULong)) || (NULL == CU_add_test(pSuite, "strToDouble", test_strToDouble)) || (NULL == CU_add_test(pSuite, "compareStr", test_compareStr)) || (NULL == CU_add_test(pSuite, "compareStrAndNum", test_compareStrAndNum)) -- Gitblit v1.9.1