Resolve #39: Correct handling of unsigned integers
| | |
| | | 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); |
| | |
| | | * @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); |
| | |
| | | |
| | | 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); |
| | | } |
| | | |
| | | /** |
| | |
| | | * @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); |
| | |
| | | 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: |
| | |
| | | * @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; |
| | | |
| | |
| | | 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; |
| | |
| | | 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 |
| | |
| | | } |
| | | |
| | | /** |
| | | * 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 |
| | |
| | | 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; |
| | |
| | | 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 |
| | |
| | | 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; |
| | |
| | | || (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)) |