Add array result functions
| | |
| | | |
| | | 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); |
| | |
| | | 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 |
| | |
| | | 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) { |
| | |
| | | } |
| | | |
| | | /** |
| | | * 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] = '#'; |
| | |
| | | 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; |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | #if USE_COMMAND_TAGS |
| | | |
| | | /** |
| | | * Return the .tag field of the matching scpi_command_t |
| | | * @param context |
| | |
| | | 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); |
| | | } |
| | |
| | | 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); |
| | | } |
| | |
| | | * 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: |
| | |
| | | * 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 |
| | |
| | | /** |
| | | * @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 |
| | |
| | | #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 |
| | |
| | | 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; |
| | |
| | | || (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(); |