From 3b99af699baba3ddbec2fbe74af6392678fbe31d Mon Sep 17 00:00:00 2001 From: Jan Breuer <jan.breuer@jaybee.cz> Date: 周二, 10 11月 2015 01:04:30 +0800 Subject: [PATCH] Add array result functions --- libscpi/inc/scpi/types.h | 10 + libscpi/src/parser.c | 249 ++++++++++++++++++++++++++++++++++- libscpi/test/test_scpi_utils.c | 19 ++ libscpi/src/utils_private.h | 15 + libscpi/inc/scpi/parser.h | 23 +++ libscpi/src/utils.c | 47 ++++++ 6 files changed, 350 insertions(+), 13 deletions(-) diff --git a/libscpi/inc/scpi/parser.h b/libscpi/inc/scpi/parser.h index b645dfe..4cc088d 100644 --- a/libscpi/inc/scpi/parser.h +++ b/libscpi/inc/scpi/parser.h @@ -50,16 +50,37 @@ size_t SCPI_ResultCharacters(scpi_t * context, const char * data, size_t len); #define SCPI_ResultMnemonic(context, data) SCPI_ResultCharacters((context), (data), strlen(data)) +#define SCPI_ResultUInt8Base SCPI_ResultUInt32Base +#define SCPI_ResultUInt8(c, v) SCPI_ResultUInt32Base((c), (v), 10) +#define SCPI_ResultInt8 SCPI_ResultInt32 +#define SCPI_ResultUInt16Base SCPI_ResultUInt32Base +#define SCPI_ResultUInt16(c, v) SCPI_ResultUInt32Base((c), (v), 10) +#define SCPI_ResultInt16 SCPI_ResultInt32 size_t SCPI_ResultUInt32Base(scpi_t * context, uint32_t val, int8_t base); +#define SCPI_ResultUInt32(c, v) SCPI_ResultUInt32Base((c), (v), 10) size_t SCPI_ResultInt32(scpi_t * context, int32_t val); size_t SCPI_ResultUInt64Base(scpi_t * context, uint64_t val, int8_t base); +#define SCPI_ResultUInt64(c, v) SCPI_ResultUInt64Base((c), (v), 10) size_t SCPI_ResultInt64(scpi_t * context, int64_t val); size_t SCPI_ResultFloat(scpi_t * context, float val); size_t SCPI_ResultDouble(scpi_t * context, double val); size_t SCPI_ResultText(scpi_t * context, const char * data); - size_t SCPI_ResultArbitraryBlock(scpi_t * context, const char * data, size_t len); + size_t SCPI_ResultArbitraryBlock(scpi_t * context, const void * data, size_t len); + size_t SCPI_ResultArbitraryBlockHeader(scpi_t * context, size_t len); + size_t SCPI_ResultArbitraryBlockData(scpi_t * context, const void * data, size_t len); size_t SCPI_ResultBool(scpi_t * context, scpi_bool_t val); + size_t SCPI_ResultArrayInt8(scpi_t * context, const int8_t * array, size_t count, scpi_array_format_t format); + size_t SCPI_ResultArrayUInt8(scpi_t * context, const uint8_t * array, size_t count, scpi_array_format_t format); + size_t SCPI_ResultArrayInt16(scpi_t * context, const int16_t * array, size_t count, scpi_array_format_t format); + size_t SCPI_ResultArrayUInt16(scpi_t * context, const uint16_t * array, size_t count, scpi_array_format_t format); + size_t SCPI_ResultArrayInt32(scpi_t * context, const int32_t * array, size_t count, scpi_array_format_t format); + size_t SCPI_ResultArrayUInt32(scpi_t * context, const uint32_t * array, size_t count, scpi_array_format_t format); + size_t SCPI_ResultArrayInt64(scpi_t * context, const int64_t * array, size_t count, scpi_array_format_t format); + size_t SCPI_ResultArrayUInt64(scpi_t * context, const uint64_t * array, size_t count, scpi_array_format_t format); + size_t SCPI_ResultArrayFloat(scpi_t * context, const float * array, size_t count, scpi_array_format_t format); + size_t SCPI_ResultArrayDouble(scpi_t * context, const double * array, size_t count, scpi_array_format_t format); + scpi_bool_t SCPI_Parameter(scpi_t * context, scpi_parameter_t * parameter, scpi_bool_t mandatory); scpi_bool_t SCPI_ParamIsValid(scpi_parameter_t * parameter); scpi_bool_t SCPI_ParamErrorOccurred(scpi_t * context); diff --git a/libscpi/inc/scpi/types.h b/libscpi/inc/scpi/types.h index 38ee018..4d56a82 100644 --- a/libscpi/inc/scpi/types.h +++ b/libscpi/inc/scpi/types.h @@ -303,8 +303,18 @@ void * user_context; scpi_parser_state_t parser_state; const char * idn[4]; + size_t arbitrary_reminding; }; + enum _scpi_array_format_t { + SCPI_FORMAT_ASCII = 0, + SCPI_FORMAT_NORMAL = 1, + SCPI_FORMAT_SWAPPED = 2, + SCPI_FORMAT_BIGENDIAN = SCPI_FORMAT_NORMAL, + SCPI_FORMAT_LITTLEENDIAN = SCPI_FORMAT_SWAPPED, + }; + typedef enum _scpi_array_format_t scpi_array_format_t; + #ifdef __cplusplus } #endif diff --git a/libscpi/src/parser.c b/libscpi/src/parser.c index 62dc151..faaeb3f 100644 --- a/libscpi/src/parser.c +++ b/libscpi/src/parser.c @@ -129,6 +129,7 @@ context->cmd_error = FALSE; context->output_count = 0; context->input_count = 0; + context->arbitrary_reminding = 0; /* if callback exists - call command callback */ if (cmd->callback != NULL) { @@ -486,14 +487,12 @@ } /** - * Write arbitrary block program data to the result + * Write arbitrary block header with length * @param context - * @param data * @param len * @return */ -size_t SCPI_ResultArbitraryBlock(scpi_t * context, const char * data, size_t len) { - size_t result = 0; +size_t SCPI_ResultArbitraryBlockHeader(scpi_t * context, size_t len) { char block_header[12]; size_t header_len; block_header[0] = '#'; @@ -502,10 +501,44 @@ header_len = strlen(block_header + 2); block_header[1] = (char) (header_len + '0'); - result += writeData(context, block_header, header_len + 2); - result += writeData(context, data, len); + context->arbitrary_reminding = len; + return writeData(context, block_header, header_len + 2); +} - context->output_count++; +/** + * Add data to arbitrary block + * @param context + * @param data + * @param len + * @return + */ +size_t SCPI_ResultArbitraryBlockData(scpi_t * context, const void * data, size_t len) { + + if (context->arbitrary_reminding < len) { + SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); + return 0; + } + + context->arbitrary_reminding -= len; + + if (context->arbitrary_reminding == 0) { + context->output_count++; + } + + return writeData(context, (const char *) data, len); +} + +/** + * Write arbitrary block program data to the result + * @param context + * @param data + * @param len + * @return + */ +size_t SCPI_ResultArbitraryBlock(scpi_t * context, const void * data, size_t len) { + size_t result = 0; + result += SCPI_ResultArbitraryBlockHeader(context, len); + result += SCPI_ResultArbitraryBlockData(context, data, len); return result; } @@ -1351,6 +1384,7 @@ } #if USE_COMMAND_TAGS + /** * Return the .tag field of the matching scpi_command_t * @param context @@ -1391,3 +1425,204 @@ scpi_bool_t SCPI_ParamErrorOccurred(scpi_t * context) { return context->cmd_error; } + +/** + * Result binary array and swap bytes if needed (native endiannes != required endiannes) + * @param context + * @param array + * @param count + * @param item_size + * @param format + * @return + */ +static size_t parserResultArrayBinary(scpi_t * context, const void * array, size_t count, size_t item_size, scpi_array_format_t format) { + + if (SCPI_GetNativeFormat() == format) { + switch (item_size) { + case 1: + case 2: + case 4: + case 8: + return SCPI_ResultArbitraryBlock(context, array, count * item_size); + default: + SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); + return 0; + } + } else { + size_t result = 0; + size_t i; + switch (item_size) { + case 1: + case 2: + case 4: + case 8: + result += SCPI_ResultArbitraryBlockHeader(context, count * item_size); + default: + SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); + return 0; + } + + switch (item_size) { + case 1: + result += SCPI_ResultArbitraryBlockData(context, array, count); + break; + case 2: + for (i = 0; i < count; i++) { + uint16_t val = SCPI_Swap16(((uint16_t*)array)[i]); + result += SCPI_ResultArbitraryBlockData(context, &val, item_size); + } + break; + case 4: + for (i = 0; i < count; i++) { + uint32_t val = SCPI_Swap32(((uint32_t*)array)[i]); + result += SCPI_ResultArbitraryBlockData(context, &val, item_size); + } + break; + case 8: + for (i = 0; i < count; i++) { + uint64_t val = SCPI_Swap64(((uint64_t*)array)[i]); + result += SCPI_ResultArbitraryBlockData(context, &val, item_size); + } + break; + } + + return result; + } +} + + +#define RESULT_ARRAY(func) do {\ + size_t result;\ + if (format == SCPI_FORMAT_ASCII) {\ + size_t i;\ + for (i = 0; i < count; i++) {\ + result += func(context, array[i]);\ + }\ + if (count > 0) {\ + result += count - 1; /* add length of commas */\ + }\ + } else {\ + result = parserResultArrayBinary(context, array, count, sizeof(*array), format);\ + }\ + return result;\ +} while(0) + +/** + * Result array of signed 8bit integers + * @param context + * @param array + * @param count + * @param format + * @return + */ +size_t SCPI_ResultArrayInt8(scpi_t * context, const int8_t * array, size_t count, scpi_array_format_t format) { + RESULT_ARRAY(SCPI_ResultInt8); +} + +/** + * Result array of unsigned 8bit integers + * @param context + * @param array + * @param count + * @param format + * @return + */ +size_t SCPI_ResultArrayUInt8(scpi_t * context, const uint8_t * array, size_t count, scpi_array_format_t format) { + RESULT_ARRAY(SCPI_ResultUInt8); +} + +/** + * Result array of signed 16bit integers + * @param context + * @param array + * @param count + * @param format + * @return + */ +size_t SCPI_ResultArrayInt16(scpi_t * context, const int16_t * array, size_t count, scpi_array_format_t format) { + RESULT_ARRAY(SCPI_ResultInt16); +} + +/** + * Result array of unsigned 16bit integers + * @param context + * @param array + * @param count + * @param format + * @return + */ +size_t SCPI_ResultArrayUInt16(scpi_t * context, const uint16_t * array, size_t count, scpi_array_format_t format) { + RESULT_ARRAY(SCPI_ResultUInt16); +} + +/** + * Result array of signed 32bit integers + * @param context + * @param array + * @param count + * @param format + * @return + */ +size_t SCPI_ResultArrayInt32(scpi_t * context, const int32_t * array, size_t count, scpi_array_format_t format) { + RESULT_ARRAY(SCPI_ResultInt32); +} + +/** + * Result array of unsigned 32bit integers + * @param context + * @param array + * @param count + * @param format + * @return + */ +size_t SCPI_ResultArrayUInt32(scpi_t * context, const uint32_t * array, size_t count, scpi_array_format_t format) { + RESULT_ARRAY(SCPI_ResultUInt32); +} + +/** + * Result array of signed 64bit integers + * @param context + * @param array + * @param count + * @param format + * @return + */ +size_t SCPI_ResultArrayInt64(scpi_t * context, const int64_t * array, size_t count, scpi_array_format_t format) { + RESULT_ARRAY(SCPI_ResultInt64); +} + +/** + * Result array of unsigned 64bit integers + * @param context + * @param array + * @param count + * @param format + * @return + */ +size_t SCPI_ResultArrayUInt64(scpi_t * context, const uint64_t * array, size_t count, scpi_array_format_t format) { + RESULT_ARRAY(SCPI_ResultUInt64); +} + +/** + * Result array of floats + * @param context + * @param array + * @param count + * @param format + * @return + */ +size_t SCPI_ResultArrayFloat(scpi_t * context, const float * array, size_t count, scpi_array_format_t format) { + RESULT_ARRAY(SCPI_ResultFloat); +} + +/** + * Result array of doubles + * @param context + * @param array + * @param count + * @param format + * @return + */ +size_t SCPI_ResultArrayDouble(scpi_t * context, const double * array, size_t count, scpi_array_format_t format) { + RESULT_ARRAY(SCPI_ResultDouble); +} diff --git a/libscpi/src/utils.c b/libscpi/src/utils.c index f69428d..7902569 100644 --- a/libscpi/src/utils.c +++ b/libscpi/src/utils.c @@ -928,3 +928,50 @@ strncpy(__s, buffer, __ssize); return __s; } + +/** + * Get native CPU endiannes + * @return + */ +scpi_array_format_t SCPI_GetNativeFormat(void) { + // @todo: endianity runtime test + return SCPI_FORMAT_LITTLEENDIAN; +} + +/** + * Swap 16bit number + * @param val + * @return + */ +uint16_t SCPI_Swap16(uint16_t val) { + return ((val & 0x00FF) << 8) | + ((val & 0xFF00) >> 8); +} + +/** + * Swap 32bit number + * @param val + * @return + */ +uint32_t SCPI_Swap32(uint32_t val) { + return ((val & 0x000000FF) << 24) | + ((val & 0x0000FF00) << 8) | + ((val & 0x00FF0000) >> 8) | + ((val & 0xFF000000) >> 24); +} + +/** + * Swap 64bit number + * @param val + * @return + */ +uint64_t SCPI_Swap64(uint64_t val) { + return ((val & 0x00000000000000FFul) << 56) | + ((val & 0x000000000000FF00ul) << 40) | + ((val & 0x0000000000FF0000ul) << 24) | + ((val & 0x00000000FF000000ul) << 8) | + ((val & 0x000000FF00000000ul) >> 8) | + ((val & 0x0000FF0000000000ul) >> 24) | + ((val & 0x00FF000000000000ul) >> 40) | + ((val & 0xFF00000000000000ul) >> 56); +} \ No newline at end of file diff --git a/libscpi/src/utils_private.h b/libscpi/src/utils_private.h index b96d73d..671dea0 100644 --- a/libscpi/src/utils_private.h +++ b/libscpi/src/utils_private.h @@ -2,7 +2,7 @@ * Copyright (c) 2012-2013 Jan Breuer, * * All Rights Reserved - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: @@ -11,7 +11,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -28,10 +28,10 @@ /** * @file scpi_utils.h * @date Thu Nov 15 10:58:45 UTC 2012 - * + * * @brief Conversion routines and string manipulation routines - * - * + * + * */ #ifndef SCPI_UTILS_PRIVATE_H @@ -74,6 +74,11 @@ #define SCPI_DTOSTRE_PLUS_SIGN 4 char * SCPI_dtostre(double __val, char * __s, size_t __ssize, unsigned char __prec, unsigned char __flags); + scpi_array_format_t SCPI_GetNativeFormat(void); + uint16_t SCPI_Swap16(uint16_t val); + uint32_t SCPI_Swap32(uint32_t val); + uint64_t SCPI_Swap64(uint64_t val); + #if !HAVE_STRNLEN size_t BSD_strnlen(const char *s, size_t maxlen) LOCAL; #endif diff --git a/libscpi/test/test_scpi_utils.c b/libscpi/test/test_scpi_utils.c index f13f63b..98a7305 100644 --- a/libscpi/test/test_scpi_utils.c +++ b/libscpi/test/test_scpi_utils.c @@ -726,6 +726,24 @@ TEST_COMPOSE_COMMAND(":A;C", 2, 3, 1, ":C", TRUE); } +static void test_swap(void) { +#define TEST_SWAP(l, a, b) CU_ASSERT_EQUAL(SCPI_Swap##l(a), b) + + TEST_SWAP(16, 0x0011, 0x1100); + TEST_SWAP(16, 0x1234, 0x3412); + + TEST_SWAP(32, 0x00000011, 0x11000000); + TEST_SWAP(32, 0x00001234, 0x34120000); + TEST_SWAP(32, 0x00AB1234, 0x3412AB00); + TEST_SWAP(32, 0xCDAB1234, 0x3412ABCD); + + TEST_SWAP(64, 0x0000000000000011ull, 0x1100000000000000ull); + TEST_SWAP(64, 0x0000000000001234ull, 0x3412000000000000ull); + TEST_SWAP(64, 0x0000000000AB1234ull, 0x3412AB0000000000ull); + TEST_SWAP(64, 0x00000000CDAB1234ull, 0x3412ABCD00000000ull); + TEST_SWAP(64, 0x123456789ABCDEF0ull, 0xF0DEBC9A78563412ull); +} + int main() { unsigned int result; CU_pSuite pSuite = NULL; @@ -761,6 +779,7 @@ || (NULL == CU_add_test(pSuite, "matchPattern", test_matchPattern)) || (NULL == CU_add_test(pSuite, "matchCommand", test_matchCommand)) || (NULL == CU_add_test(pSuite, "composeCompoundCommand", test_composeCompoundCommand)) + || (NULL == CU_add_test(pSuite, "swap", test_swap)) ) { CU_cleanup_registry(); return CU_get_error(); -- Gitblit v1.9.1