var_export.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-06-04 WillianChan first version
  9. * 2021-06-08 WillianChan support to MS VC++ compiler
  10. */
  11. #include <var_export.h>
  12. static const ve_exporter_t *ve_exporter_table = RT_NULL;
  13. static rt_size_t ve_exporter_num = 0;
  14. /* for IAR compiler */
  15. #if defined(__ICCARM__) || defined(__ICCRX__)
  16. #pragma section="VarExpTab"
  17. #endif
  18. /* for ARM C and IAR Compiler */
  19. #if defined(__CC_ARM) || defined(__CLANG_ARM) || defined (__ICCARM__) || defined(__ICCRX__)
  20. static RT_USED const struct ve_exporter __ve_table_start
  21. RT_SECTION("0.""VarExpTab") = {"ve_start", "ve_start", 0};
  22. static RT_USED const struct ve_exporter __ve_table_end
  23. RT_SECTION("2.""VarExpTab") = {"ve_end", "ve_end", 2};
  24. #endif
  25. /* for MS VC++ compiler */
  26. #if defined(_MSC_VER)
  27. #pragma section("VarExpTab$a", read)
  28. __declspec(allocate("VarExpTab$a"))
  29. RT_USED const struct ve_exporter __ve_table_start = { "ve_start", "ve_start", 0};
  30. #pragma section("VarExpTab$z", read)
  31. __declspec(allocate("VarExpTab$z"))
  32. RT_USED const struct ve_exporter __ve_table_end = { "ve_end", "ve_end", 2};
  33. #endif
  34. /* initialize var export */
  35. int var_export_init(void)
  36. {
  37. /* initialize the var export table.*/
  38. #if defined(__CC_ARM) || defined(__CLANG_ARM) /* for ARM C Compiler */
  39. ve_exporter_table = &__ve_table_start + 1;
  40. ve_exporter_num = &__ve_table_end - &__ve_table_start;
  41. #elif defined (__GNUC__) /* for GCC Compiler */
  42. extern const int __ve_table_start;
  43. extern const int __ve_table_end;
  44. ve_exporter_table = (const ve_exporter_t *)&__ve_table_start;
  45. ve_exporter_num = (const ve_exporter_t *)&__ve_table_end - ve_exporter_table;
  46. #elif defined (__ICCARM__) || defined(__ICCRX__) /* for IAR Compiler */
  47. ve_exporter_table = &__ve_table_start + 1;
  48. ve_exporter_num = &__ve_table_end - &__ve_table_start - 1;
  49. #elif defined (_MSC_VER) /* for MS VC++ compiler */
  50. unsigned int *ptr_begin = (unsigned int *)&__ve_table_start;
  51. unsigned int *ptr_end = (unsigned int *)&__ve_table_end;
  52. static ve_exporter_t ve_exporter_tab[2048];
  53. ve_exporter_t ve_exporter_temp;
  54. int index_i, index_j, index_min;
  55. /* past the three members in first ptr_begin */
  56. ptr_begin += (sizeof(struct ve_exporter) / sizeof(unsigned int));
  57. while (*ptr_begin == 0) ptr_begin++;
  58. do ptr_end--; while (*ptr_end == 0);
  59. ve_exporter_table = (const ve_exporter_t *)ptr_begin;
  60. ve_exporter_num = (ptr_end - ptr_begin) / (sizeof(struct ve_exporter) / sizeof(unsigned int)) + 1;
  61. for (index_i = 0; index_i < ve_exporter_num; index_i++)
  62. {
  63. ve_exporter_tab[index_i] = ve_exporter_table[index_i];
  64. }
  65. for (index_i = 0; index_i < (ve_exporter_num - 1); index_i++)
  66. {
  67. index_min = index_i;
  68. for (index_j = index_i + 1; index_j < ve_exporter_num; index_j++)
  69. {
  70. if (rt_strcmp(ve_exporter_tab[index_j].module, ve_exporter_tab[index_min].module) < 0 &&
  71. rt_strcmp(ve_exporter_tab[index_j].identifier, ve_exporter_tab[index_min].identifier) < 0)
  72. {
  73. index_min = index_j;
  74. ve_exporter_temp = ve_exporter_tab[index_min];
  75. ve_exporter_tab[index_min] = ve_exporter_tab[index_i];
  76. ve_exporter_tab[index_i] = ve_exporter_temp;
  77. }
  78. }
  79. }
  80. ve_exporter_table = ve_exporter_tab;
  81. #endif /* __CC_ARM || __CLANG_ARM */
  82. return ve_exporter_num;
  83. }
  84. INIT_PREV_EXPORT(var_export_init);
  85. /* initialize module */
  86. int ve_module_init(ve_module_t *mod, const char *module)
  87. {
  88. const ve_exporter_t *exporter = ve_exporter_table;
  89. rt_bool_t first_exist = RT_FALSE;
  90. rt_size_t found_index;
  91. for (found_index = 0; found_index < ve_exporter_num; found_index++)
  92. {
  93. if (!rt_strcmp(exporter->module, module))
  94. {
  95. if (first_exist == RT_FALSE)
  96. {
  97. mod->begin = exporter;
  98. first_exist = RT_TRUE;
  99. }
  100. mod->end = exporter;
  101. }
  102. exporter++;
  103. }
  104. if (first_exist == RT_FALSE)
  105. {
  106. return -RT_ERROR;
  107. }
  108. return RT_EOK;
  109. }
  110. /* initialize iterator */
  111. void ve_iter_init(ve_module_t *mod, ve_iterator_t *iter)
  112. {
  113. if (iter)
  114. {
  115. iter->exp_index = mod->begin;
  116. iter->exp_end = mod->end;
  117. }
  118. }
  119. /* iterate backward */
  120. const ve_exporter_t *ve_iter_next(ve_iterator_t *iter)
  121. {
  122. if (iter->exp_index <= iter->exp_end)
  123. {
  124. return iter->exp_index++;
  125. }
  126. else
  127. {
  128. return RT_NULL;
  129. }
  130. }
  131. /* binary search based on identifier */
  132. static const ve_exporter_t *ve_binary_search(ve_module_t *mod, const char *identifier)
  133. {
  134. rt_size_t ve_low_num = mod->begin - ve_exporter_table;
  135. rt_size_t ve_high_num = mod->end - ve_exporter_table;
  136. rt_size_t ve_mid_num;
  137. int strcmp_rst;
  138. while (ve_low_num <= ve_high_num)
  139. {
  140. ve_mid_num = (ve_high_num - ve_low_num) / 2;
  141. strcmp_rst = rt_strcmp(mod->begin[ve_mid_num].identifier, identifier);
  142. if (strcmp_rst == 0)
  143. {
  144. return &mod->begin[ve_mid_num];
  145. }
  146. else if (strcmp_rst > 0)
  147. {
  148. ve_high_num = ve_mid_num + 1;
  149. }
  150. else
  151. {
  152. ve_low_num = ve_mid_num - 1;
  153. }
  154. }
  155. return RT_NULL;
  156. }
  157. /* get the value by identifier */
  158. rt_base_t ve_value_get(ve_module_t *mod, const char *identifier)
  159. {
  160. const ve_exporter_t *exporter = ve_binary_search(mod, identifier);
  161. if (exporter)
  162. {
  163. return exporter->value;
  164. }
  165. else
  166. {
  167. return VE_NOT_FOUND;
  168. }
  169. }
  170. /* check if this value exists in the module*/
  171. rt_bool_t ve_value_exist(ve_module_t *mod, const char *identifier)
  172. {
  173. if (ve_binary_search(mod, identifier))
  174. {
  175. return RT_TRUE;
  176. }
  177. else
  178. {
  179. return RT_FALSE;
  180. }
  181. }