var_export.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  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. /* check if the ve_exporter_num is out of bounds */
  62. RT_ASSERT(ve_exporter_num < (sizeof(ve_exporter_tab) / sizeof(ve_exporter_t)));
  63. for (index_i = 0; index_i < ve_exporter_num; index_i++)
  64. {
  65. ve_exporter_tab[index_i] = ve_exporter_table[index_i];
  66. }
  67. for (index_i = 0; index_i < (ve_exporter_num - 1); index_i++)
  68. {
  69. index_min = index_i;
  70. for (index_j = index_i + 1; index_j < ve_exporter_num; index_j++)
  71. {
  72. if (rt_strcmp(ve_exporter_tab[index_j].module, ve_exporter_tab[index_min].module) < 0 &&
  73. rt_strcmp(ve_exporter_tab[index_j].identifier, ve_exporter_tab[index_min].identifier) < 0)
  74. {
  75. index_min = index_j;
  76. ve_exporter_temp = ve_exporter_tab[index_min];
  77. ve_exporter_tab[index_min] = ve_exporter_tab[index_i];
  78. ve_exporter_tab[index_i] = ve_exporter_temp;
  79. }
  80. }
  81. }
  82. ve_exporter_table = ve_exporter_tab;
  83. #endif /* __CC_ARM || __CLANG_ARM */
  84. return ve_exporter_num;
  85. }
  86. INIT_PREV_EXPORT(var_export_init);
  87. /* initialize module */
  88. int ve_module_init(ve_module_t *mod, const char *module)
  89. {
  90. const ve_exporter_t *exporter = ve_exporter_table;
  91. rt_bool_t first_exist = RT_FALSE;
  92. rt_size_t found_index;
  93. for (found_index = 0; found_index < ve_exporter_num; found_index++)
  94. {
  95. if (!rt_strcmp(exporter->module, module))
  96. {
  97. if (first_exist == RT_FALSE)
  98. {
  99. mod->begin = exporter;
  100. first_exist = RT_TRUE;
  101. }
  102. mod->end = exporter;
  103. }
  104. exporter++;
  105. }
  106. if (first_exist == RT_FALSE)
  107. {
  108. return -RT_ERROR;
  109. }
  110. return RT_EOK;
  111. }
  112. /* initialize iterator */
  113. void ve_iter_init(ve_module_t *mod, ve_iterator_t *iter)
  114. {
  115. if (iter)
  116. {
  117. iter->exp_index = mod->begin;
  118. iter->exp_end = mod->end;
  119. }
  120. }
  121. /* iterate backward */
  122. const ve_exporter_t *ve_iter_next(ve_iterator_t *iter)
  123. {
  124. if (iter->exp_index <= iter->exp_end)
  125. {
  126. return iter->exp_index++;
  127. }
  128. else
  129. {
  130. return RT_NULL;
  131. }
  132. }
  133. /* binary search based on identifier */
  134. static const ve_exporter_t *ve_binary_search(ve_module_t *mod, const char *identifier)
  135. {
  136. rt_size_t ve_low_num = mod->begin - ve_exporter_table;
  137. rt_size_t ve_high_num = mod->end - ve_exporter_table;
  138. rt_size_t ve_mid_num;
  139. int strcmp_rst;
  140. while (ve_low_num <= ve_high_num)
  141. {
  142. ve_mid_num = (ve_high_num - ve_low_num) / 2;
  143. strcmp_rst = rt_strcmp(mod->begin[ve_mid_num].identifier, identifier);
  144. if (strcmp_rst == 0)
  145. {
  146. return &mod->begin[ve_mid_num];
  147. }
  148. else if (strcmp_rst > 0)
  149. {
  150. ve_high_num = ve_mid_num + 1;
  151. }
  152. else
  153. {
  154. ve_low_num = ve_mid_num - 1;
  155. }
  156. }
  157. return RT_NULL;
  158. }
  159. /* get the value by identifier */
  160. rt_base_t ve_value_get(ve_module_t *mod, const char *identifier)
  161. {
  162. const ve_exporter_t *exporter = ve_binary_search(mod, identifier);
  163. if (exporter)
  164. {
  165. return exporter->value;
  166. }
  167. else
  168. {
  169. return VE_NOT_FOUND;
  170. }
  171. }
  172. /* check if this value exists in the module*/
  173. rt_bool_t ve_value_exist(ve_module_t *mod, const char *identifier)
  174. {
  175. if (ve_binary_search(mod, identifier))
  176. {
  177. return RT_TRUE;
  178. }
  179. else
  180. {
  181. return RT_FALSE;
  182. }
  183. }