Subversion Repositories dashGPS

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #ifndef _ARR_DESC_H_
  2. #define _ARR_DESC_H_
  3.  
  4. /*--------------------------------------------------------------------------------*/
  5. /* Includes */
  6. /*--------------------------------------------------------------------------------*/
  7. #include <stdint.h>
  8. #include <string.h>             /* memset() */
  9. #include "../util/util.h"       /* CONCAT() */
  10.  
  11. /*--------------------------------------------------------------------------------*/
  12. /* Type Definitions */
  13. /*--------------------------------------------------------------------------------*/
  14.  
  15. /**
  16.  *  Array-descriptor struct.
  17.  */
  18. typedef struct ARR_DESC_struct
  19. {
  20.     void *  data_ptr;                /* Pointer to the array contents. */
  21.     int32_t element_count;           /* Number of current elements. */
  22.     int32_t element_size;            /* Size of current elements in bytes. */
  23.     int32_t underlying_size;         /* Size of underlying array in bytes. */
  24. } ARR_DESC_t;
  25.  
  26. /*--------------------------------------------------------------------------------*/
  27. /* Macros and Defines */
  28. /*--------------------------------------------------------------------------------*/
  29.  
  30. /**
  31.  *  Prefix of the array variable's name when creating an array and an array
  32.  *  descriptor at the same time.
  33.  */
  34. #define ARR_DESC_ARR_PREFIX ARR_DESC_ARR_
  35.  
  36. /**
  37.  *  Evaluate to the array variable's name when creating an array and an array
  38.  *  descriptor at the same time.
  39.  */
  40. #define ARR_DESC_ARR_NAME(name)                 \
  41.     CONCAT(ARR_DESC_ARR_PREFIX, name)
  42.  
  43. /**
  44.  *  Define an #ARR_DESC_t by itself.
  45.  *
  46.  *  @note The user must supply an array to store the data used by the
  47.  *  #ARR_DESC_t.
  48.  */
  49. #define ARR_DESC_INTERNAL_DEFINE(name, data_ptr,                \
  50.                                  element_count, element_size)   \
  51.     ARR_DESC_t name = {                                         \
  52.         data_ptr,                                               \
  53.         element_count,                                          \
  54.         element_size,                                           \
  55.         element_count * element_size                            \
  56.     }                                                           \
  57.  
  58. /**
  59.  *  Define both an array and an #ARR_DESC_t that describes it.
  60.  *
  61.  *  @note Use the #CURLY() macro for the content field; it provides the curly
  62.  *  braces necessary for an array initialization.
  63.  */
  64. #define ARR_DESC_DEFINE(type, name, element_count, content)             \
  65.     type ARR_DESC_ARR_NAME(name)[element_count] = content;              \
  66.     ARR_DESC_INTERNAL_DEFINE(name,                                      \
  67.                              &ARR_DESC_ARR_NAME(name),                  \
  68.                              element_count,                             \
  69.                              sizeof(type)) /* Note the lacking semicolon */
  70.  
  71. /**
  72.  *  Create a #ARR_DESC_t which refers to a subset of the data in another.
  73.  *
  74.  *  The new #ARR_DESC_t shares the same underlying array as the aliased
  75.  *  #ARR_DESC_t, but only describes a subset of the originals values.
  76.  */
  77. #define ARR_DESC_DEFINE_SUBSET(name, original, element_cnt)         \
  78.     ARR_DESC_INTERNAL_DEFINE(name,                                  \
  79.                              &ARR_DESC_ARR_NAME(original),          \
  80.                              element_cnt,                           \
  81.                              sizeof(ARR_DESC_ARR_NAME(original)[0]) \
  82.         ) /* Note the lacking semicolon */
  83.  
  84. /**
  85.  *  Creat an #ARR_DESC_t which points to the data in an existing array.
  86.  *
  87.  *  @param start_idx Offset in array_ptr of first element.
  88.  *  @param element_cnt Number of elements to include in the #ARR_DESC_t.
  89.  *
  90.  *  @example
  91.  *
  92.  *  float my_floats[4] = {0.0f, 1.0f, 2.0f, 3.0f};
  93.  *
  94.  *  ARR_DESC_DEFINE_USING_ARR(my_arr_desc, my_floats, 1, 3);
  95.  *
  96.  *  printf("Element 0: %f\n", ARR_DESC_ELT(float, 0, &my_arr_desc));
  97.  *  printf("Element 1: %f\n", ARR_DESC_ELT(float, 1, &my_arr_desc));
  98.  *
  99.  *  Outputs:
  100.  *
  101.  *  Element 0: 1.000000
  102.  *  Element 1: 2.000000
  103.  *
  104.  *  @warning There are no checks in place to catch invalid start indices; This
  105.  *  is left to the user.
  106.  */
  107. #define ARR_DESC_DEFINE_USING_ARR(type, name, array_ptr, start_idx, element_cnt) \
  108.     ARR_DESC_INTERNAL_DEFINE(                                           \
  109.         name,                                                           \
  110.         (type *) (array_ptr + start_idx),                               \
  111.         element_cnt,                                                    \
  112.         sizeof(type)                                                    \
  113.         ) /* Note the lacking semicolon*/
  114.  
  115. /**
  116.  *  Declare an #ARR_DESC_t object.
  117.  */
  118. #define ARR_DESC_DECLARE(name)                              \
  119.     extern ARR_DESC_t name /* Note the lacking semicolon */
  120.  
  121. /**
  122.  *  Evaluate to the number of bytes stored in the #ARR_DESC_t.
  123.  */
  124. #define ARR_DESC_BYTES(arr_desc_ptr)                                \
  125.     ((arr_desc_ptr)->element_count * (arr_desc_ptr)->element_size)
  126.  
  127. /**
  128.  *  Set the contents of #ARR_DESC_t to value.
  129.  */
  130. #define ARR_DESC_MEMSET(arr_desc_ptr, value, bytes)     \
  131.     do                                                  \
  132.     {                                                   \
  133.         memset((arr_desc_ptr)->data_ptr,                \
  134.                value,                                   \
  135.                BOUND(0,                                 \
  136.                      (arr_desc_ptr)->underlying_size,   \
  137.                      bytes)                             \
  138.             );                                          \
  139.     } while (0)
  140.  
  141. /**
  142.  *  Perform a memcpy of 'bytes' bytes from the source #ARR_DESC_t to the
  143.  *  destination #ARR_DESC_t.
  144.  */
  145. #define ARR_DESC_MEMCPY(arr_desc_dest_ptr, arr_desc_src_ptr, bytes) \
  146.     do                                                              \
  147.     {                                                               \
  148.         memcpy((arr_desc_dest_ptr)->data_ptr,                       \
  149.                (arr_desc_src_ptr)->data_ptr,                        \
  150.                BOUND(0,                                             \
  151.                      (arr_desc_dest_ptr)->underlying_size,          \
  152.                      bytes));                                       \
  153.     } while (0)
  154.  
  155. /**
  156.  *  Evaluate to true if the source #ARR_DESC_t contents will fit into the
  157.  *  destination #ARR_DESC_t and false otherwise.
  158.  */
  159. #define ARR_DESC_COPYABLE(arr_desc_dest_ptr, arr_desc_src_ptr)  \
  160.       (ARR_DESC_BYTES(arr_desc_src_ptr) <=                      \
  161.        (arr_desc_dest_ptr)->underlying_size)
  162.  
  163. /**
  164.  *  Copy all the data from the source #ARR_DESC_t to the destination
  165.  *  #ARR_DESC_t.
  166.  *
  167.  *  @note If the destination #ARR_DESC_t is too small to fit the source data the
  168.  *  copy is aborted and nothing happens.
  169.  */
  170. #define ARR_DESC_COPY(arr_desc_dest_ptr, arr_desc_src_ptr)      \
  171.     do                                                          \
  172.     {                                                           \
  173.         if (ARR_DESC_COPYABLE(arr_desc_dest_ptr,                 \
  174.                              arr_desc_src_ptr))                 \
  175.         {                                                       \
  176.             ARR_DESC_MEMCPY(arr_desc_dest_ptr,                  \
  177.                             arr_desc_src_ptr,                   \
  178.                             ARR_DESC_BYTES(arr_desc_src_ptr));  \
  179.             /* Update the properties*/                          \
  180.             (arr_desc_dest_ptr)->element_count =                \
  181.                 (arr_desc_src_ptr)->element_count;              \
  182.             (arr_desc_dest_ptr)->element_size =                 \
  183.                 (arr_desc_src_ptr)->element_size;               \
  184.         }                                                       \
  185.     } while (0)
  186.  
  187. /**
  188.  *  Compare the data in two #ARR_DESC_t structs for the specified number of
  189.  *  bytes.
  190.  */
  191. #define ARR_DESC_MEMCMP(arr_desc_ptr_a, arr_desc_ptr_b, bytes)  \
  192.         memcmp((arr_desc_ptr_a)->data_ptr,                      \
  193.             (arr_desc_ptr_b)->data_ptr,                         \
  194.                bytes) /* Note the lacking semicolon */          \
  195.  
  196. /**
  197.  *  Zero out the contents of the #ARR_DESC_t.
  198.  */
  199. #define ARR_DESC_ZERO(arr_desc_ptr)             \
  200.         ARR_DESC_MEMSET(arr_desc_ptr,           \
  201.                         0,                      \
  202.                         (arr_desc_ptr)->underlying_size)
  203.  
  204. /**
  205.  *  Evaluate to the data address in #ARR_DESC_t at offset.
  206.  */
  207. #define ARR_DESC_DATA_ADDR(type, arr_desc_ptr, offset)  \
  208.         ((void*)(((type *)                              \
  209.                   ((arr_desc_ptr)->data_ptr))           \
  210.                  + offset))
  211.  
  212. /**
  213.  *  Evaluate to the element in #ARR_DESC_t with type at idx.
  214.  */
  215. #define ARR_DESC_ELT(type, idx, arr_desc_ptr)           \
  216.         (*((type *) ARR_DESC_DATA_ADDR(type,            \
  217.                                        arr_desc_ptr,    \
  218.                                        idx)))
  219.  
  220. #endif /* _ARR_DESC_H_ */
  221.