LCOV - code coverage report
Current view: top level - src/include/macros - type_create_to_value.h (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 10 10 100.0 %
Date: 2022-05-21 16:19:22 Functions: 0 20 0.0 %

          Line data    Source code
       1             : // lgtm [cpp/missing-header-guard]
       2             : 
       3             : /**
       4             :  * @copyright BSD License (see doc/COPYING or http://www.libelektra.org)
       5             :  *
       6             :  * @brief Create key to type conversion function.
       7             :  *
       8             :  * This supermacro creates the following functions:
       9             :  * - int NAME_MACRO (TYPE_NAME) (Key * key, TYPE * variable)
      10             :  *
      11             :  * @param  TYPE             valid C type (e.g. int or kdb_short_t)
      12             :  * @param  TYPE_NAME        name suffix for the functions (e.g. Int or UnsignedLong)
      13             :  * @param  VALUE_TYPE       optional, defaults to TYPE. Ideally a larger type assigned to variable `value` for
      14             :  *                          checking the range before the variable is updated
      15             :  * @param  TO_VALUE         expression for converting `string` (variable containing the key value) to VALUE_TYPE
      16             :  * @param  CHECK_CONVERSION optional, defaults to true. A boolean expression. Allows to check the range after
      17             :  *                          conversion. Use ELEKTRA_TYPE_CHECK_CONVERSION to check if a conversion using
      18             :  *                          strto*()-functions was successful and ELEKTRA_TYPE_CHECK_CONVERSION_RANGE (RANGE)
      19             :  *                          to check additionally for a specified range.
      20             :  * @param  CHECK_FAIL_BLOCK optional, defaults to logging a warning in the key. The code to be executed (before returning 0), if
      21             :  *                          CHECK_CONVERSION evaluates to false.
      22             :  * @param  PRE_CHECK_CONVERSION_BLOCK optional, defaults to empty. Allows to add additional code for pre-conversion checks
      23             :  *                                    (e.g. ELEKTRA_TYPE_NEGATIVE_PRE_CHECK_BLOCK)
      24             :  * @param  PRE_CHECK_CONVERSION       optional, defaults to true. A boolean expression to check the contents of `string` before conversion
      25             :  *                                    (e.g. ELEKTRA_TYPE_NEGATIVE_PRE_CHECK).
      26             :  * @param  PRE_CHECK_FAIL_BLOCK       optional, defaults to logging a warning in the key. The code to be executed (before returning 0), if
      27             :  *                                    PRE_CHECK_CONVERSION evaluates to false.
      28             :  * @param  DISABLE_UNDEF_PARAMETERS   define to disable undefining of parameters after the macro. Use if parameters
      29             :  *                                    are used within another supermacro.
      30             :  * @param  CODE_ONLY           optional, defaults to 0. Set to 1 to only generate the function body. This is useful, if you want to create a
      31             :  *                             function with a custom signature for example.
      32             :  * @param  KEY_PARAM_NAME      must be set, #if CODE_ONLY, will be set to 'key' otherwise. The name of the variable/parameter containing
      33             :  *                             the Key, whose value will be converted
      34             :  * @param  VARIABLE_PARAM_NAME must be set, #if CODE_ONLY, will be set to 'variable' otherwise. The name of the variable/parameter
      35             :  *                             containing the pointer to where the result should be written
      36             :  */
      37             : #ifndef TYPE
      38             : #error "You have to #define TYPE, TYPE_NAME, TO_VALUE and NAME_MACRO before including the type_create_to_value supermacro"
      39             : #endif
      40             : #ifndef VALUE_TYPE
      41             : // use type as default if not set
      42             : #define VALUE_TYPE TYPE
      43             : #endif
      44             : #ifndef TYPE_NAME
      45             : #error "You have to #define TYPE, TYPE_NAME, TO_VALUE and NAME_MACRO before including the type_create_to_value supermacro"
      46             : #endif
      47             : #ifndef NAME_MACRO
      48             : #error "You have to #define TYPE, TYPE_NAME, TO_VALUE and NAME_MACRO before including the type_create_to_value supermacro"
      49             : #endif
      50             : #ifndef TO_VALUE
      51             : #error "You have to #define TYPE, TYPE_NAME, TO_VALUE and NAME_MACRO before including the type_create_to_value supermacro"
      52             : #endif
      53             : #ifndef CHECK_CONVERSION
      54             : #define CHECK_CONVERSION 1
      55             : #endif
      56             : #ifndef PRE_CHECK_CONVERSION
      57             : #define PRE_CHECK_CONVERSION 1
      58             : #endif
      59             : #ifndef PRE_CHECK_BLOCK
      60             : #define PRE_CHECK_BLOCK
      61             : #endif
      62             : #ifndef PRE_CHECK_FAIL_BLOCK
      63             : #define PRE_CHECK_FAIL_BLOCK ELEKTRA_LOG_WARNING ("pre-check for type conversion failed! string=%s", keyString (key));
      64             : #endif
      65             : #ifndef CHECK_FAIL_BLOCK
      66             : #define CHECK_FAIL_BLOCK ELEKTRA_LOG_WARNING ("type conversion failed! string=%s, stopped=%c errno=%d", keyString (key), *end, errno);
      67             : #endif
      68             : #ifndef CODE_ONLY
      69             : #define CODE_ONLY 0
      70             : #endif
      71             : 
      72             : #if CODE_ONLY
      73             : #if (!defined(KEY_PARAM_NAME) || !defined(VARIABLE_PARAM_NAME))
      74             : #error "When CODE_ONLY is defined, you have to #define KEY_PARAM_NAME and VARIABLE_PARAM_NAME"
      75             : #endif
      76             : #else
      77             : #undef KEY_PARAM_NAME
      78             : #undef VARIABLE_PARAM_NAME
      79             : #define KEY_PARAM_NAME key
      80             : #define VARIABLE_PARAM_NAME variable
      81             : #endif
      82             : 
      83             : // These macros get defined at first inclusion
      84             : #ifndef ELEKTRA_TYPE_CONVERSION_MACROS
      85             : #define ELEKTRA_TYPE_CONVERSION_MACROS
      86             : #define ELEKTRA_TYPE_CHECK_CONVERSION (*end == 0 && errno == 0)
      87             : #define ELEKTRA_TYPE_CHECK_CONVERSION_RANGE(CHECK_RANGE) (ELEKTRA_TYPE_CHECK_CONVERSION && CHECK_RANGE)
      88             : #define ELEKTRA_TYPE_NEGATIVE_PRE_CHECK_BLOCK                                                                                              \
      89             :         const char * test = string;                                                                                                        \
      90             :         while (isspace (test[0]) || test[0] == 0)                                                                                          \
      91             :         {                                                                                                                                  \
      92             :                 test++;                                                                                                                    \
      93             :         }
      94             : #define ELEKTRA_TYPE_NEGATIVE_PRE_CHECK (test[0] != '-')
      95             : #endif
      96             : 
      97             : #if !(CODE_ONLY)
      98             : #include <errno.h> // errno
      99             : 
     100             : #define TYPE_CONVERSION_SIGNATURE(TYPE, TYPE_NAME, NAME_MACRO)                                                                             \
     101             :         int NAME_MACRO (TYPE_NAME) (const Key * KEY_PARAM_NAME, TYPE * VARIABLE_PARAM_NAME)
     102             : 
     103             : /**
     104             :  * Convert string to TYPE.
     105             :  *
     106             :  * The variable is only changed if no conversion error occurred
     107             :  *
     108             :  * Example:
     109             :  * int variable = 1234;
     110             :  * if (!NAME_MACRO (TYPE_NAME) (key, &variable))
     111             :  * {
     112             :  *   // conversion failed
     113             :  *   // variable == 1234
     114             :  * }
     115             :  * // variable was changed
     116             :  *
     117             :  * @param key        key
     118             :  * @param variable   pointer to variable
     119             :  * @retval 1 on success
     120             :  * @retval 0 on conversion error
     121             :  */
     122         138 : TYPE_CONVERSION_SIGNATURE (TYPE, TYPE_NAME, NAME_MACRO)
     123             : {
     124             : #endif
     125        2670 :         char * end ELEKTRA_UNUSED;
     126        2670 :         const char * string = keyValue (KEY_PARAM_NAME);
     127        2670 :         errno = 0;
     128         400 :         PRE_CHECK_BLOCK
     129         677 :         if (!PRE_CHECK_CONVERSION)
     130             :         {
     131             :                 PRE_CHECK_FAIL_BLOCK
     132             :                 return 0;
     133             :         }
     134             :         // convert string to target type
     135        1932 :         VALUE_TYPE value = TO_VALUE;
     136        1932 :         if (CHECK_CONVERSION)
     137             :         {
     138             :                 // only update if conversion was successful
     139        2532 :                 *(VARIABLE_PARAM_NAME) = (TYPE) value;
     140        1989 :                 return 1;
     141             :         }
     142             :         else
     143             :         {
     144             :                 CHECK_FAIL_BLOCK
     145             :                 return 0;
     146             :         }
     147             : #if !(CODE_ONLY)
     148             : }
     149             : 
     150             : #undef TYPE_CONVERSION_SIGNATURE
     151             : #endif
     152             : 
     153             : #ifndef DISABLE_UNDEF_PARAMETERS
     154             : #undef TYPE
     155             : #undef VALUE_TYPE
     156             : #undef TYPE_NAME
     157             : #undef NAME_MACRO
     158             : #undef TO_VALUE
     159             : #undef CHECK_CONVERSION
     160             : #undef PRE_CHECK_BLOCK
     161             : #undef PRE_CHECK_CONVERSION
     162             : #undef PRE_CHECK_FAIL_BLOCK
     163             : #undef CHECK_FAIL_BLOCK
     164             : #undef CODE_ONLY
     165             : #undef KEY_PARAM_NAME
     166             : #undef VARIABLE_PARAM_NAME
     167             : #endif
     168             : #undef DISABLE_UNDEF_PARAMETERS

Generated by: LCOV version 1.13