Advertisement
mabruzzo

Alternative implementation of dynamic_api.c

Dec 1st, 2022
1,073
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.54 KB | None | 0 0
  1. /***********************************************************************
  2. /
  3. / Defines functions that provide access to fields of the chemistry_data
  4. / struct by dynamically specifying strings. If external applications use
  5. / these functions to access/set fields, rather than directly accessing
  6. / the fields of the struct, the applications will be to maintain
  7. / compatability with multiple versions grackle (as more fields get added
  8. / to chemistry_data)
  9. /
  10. /
  11. / Copyright (c) 2013, Enzo/Grackle Development Team.
  12. /
  13. / Distributed under the terms of the Enzo Public Licence.
  14. /
  15. / The full license is in the file LICENSE, distributed with this
  16. / software.
  17. ************************************************************************/
  18.  
  19. #include <stddef.h>
  20. #include <string.h>
  21. #include "grackle_chemistry_data.h"
  22.  
  23. // initialize _param_list_int and _param_list_double, which respectively hold
  24. // an entry for each int and double field in chemistry_data. These are only
  25. // used internally
  26. typedef struct { const size_t offset; const char * name; } param_entry;
  27.  
  28. #define _LIST_INT_INT(FIELD) {offsetof(chemistry_data, FIELD), #FIELD},
  29. #define _LIST_INT_DOUBLE(FIELD) /* ... */
  30. #define _LIST_INT_STRING(FIELD) /* ... */
  31.  
  32. #define _LIST_DOUBLE_INT(FIELD) /* ... */
  33. #define _LIST_DOUBLE_DOUBLE(FIELD) {offsetof(chemistry_data, FIELD), #FIELD},
  34. #define _LIST_DOUBLE_STRING(FIELD) /* ... */
  35.  
  36. static const param_entry _int_param_list[] = {
  37.   #define ENTRY(FIELD, TYPE, DEFAULT_VAL) _LIST_ELEM_INT_ ## TYPE(FIELD)
  38.   #include "grackle_chemistry_data_fields.def"
  39.   #undef ENTRY
  40. };
  41.  
  42. static const param_entry _double_param_list[] = {
  43.   #define ENTRY(FIELD, TYPE, DEFAULT_VAL) _LIST_ELEM_DOUBLE_ ## TYPE(FIELD)
  44.   #include "grackle_chemistry_data_fields.def"
  45.   #undef ENTRY
  46. };
  47.  
  48.  
  49. // initialize _n_int_params and _n_double_params, which respectively store the
  50. // lengths of _int_param_list & _double_param_list
  51. static const size_t _n_int_params =
  52.   sizeof(_int_param_list) / sizeof(param_entry);
  53. static const size_t _n_double_params =
  54.   sizeof(_double_param_list) / sizeof(param_entry);
  55.  
  56.  
  57. // define functions for accessing field values
  58. // - local_chemistry_data_access_double
  59. // - local_chemistry_data_access_int
  60. //
  61. // The current implementation has O(N) complexity where N is the number of
  62. // fields of chemistry_data. Since configuration just happens once, this
  63. // probably doesn't need to be very fast...
  64. //
  65. // A faster implementation that does a lot less work at runtime is definitely
  66. // possible (it would just involve more code).
  67.  
  68. // retrieves a pointer to the field of my_chemistry that's named ``name``.
  69. //
  70. // This returns a NULL pointer if: my_chemistry is NULL, the field doesn't
  71. // exist, or the field doesn't have the specified type
  72. static void* _get_field_ptr(chemistry_data* my_chemistry, const char* name,
  73.                             int is_int)
  74. {
  75.   if (my_chemistry == NULL) { return NULL; }
  76.  
  77.   const param_entry* l = (is_int == 1) ? _int_param_list : _double_param_list;
  78.   const size_t length = (is_int == 1) ? _n_int_params : _n_double_params;
  79.  
  80.   for (size_t param_index = 0; param_index < length; param_index++){
  81.     const param_entry* entry = l + param_index;
  82.     if (strcmp(entry->name, name) == 0){
  83.       return (void*)( (char*)my_chemistry + entry->offset );
  84.     }
  85.   }
  86.   return NULL;
  87. }
  88.  
  89. double* local_chemistry_data_access_double(chemistry_data* my_chemistry,
  90.                                            const char* param_name)
  91. { return (double*)_get_field_ptr(my_chemistry, param_name, 0); }
  92.  
  93. int* local_chemistry_data_access_int(chemistry_data* my_chemistry,
  94.                                      const char* param_name)
  95. { return (int*)_get_field_ptr(my_chemistry, param_name, 1); }
  96.  
  97. // define functions for accessing the names of chemistry_data
  98. // - param_name_double
  99. // - param_name_int
  100. //
  101. // These are primarily needed for testing purposes and can be used for
  102. // serialization. The current implementation is slow. A faster alternative
  103. // would define separate lists for int parameters and double parameters
  104.  
  105. // returns the name of the ``i``th parameter of the specified type. This returns
  106. // NULL when there are ``i`` or fewer parameters of the specified type
  107. static const char* _param_name(size_t i, int is_int)
  108. {
  109.   const param_entry* l = (is_int == 1) ? _int_param_list : _double_param_list;
  110.   size_t length = (is_int == 1) ? _n_int_params : _n_double_params;
  111.   return (i < length) ? l[i].name : NULL;
  112. }
  113.  
  114. const char* param_name_double(size_t i){ return _param_name(i, 0); }
  115. const char* param_name_int(size_t i){ return _param_name(i, 1); }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement