value.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #include "pcilib.h"
  6. #include "value.h"
  7. #include "error.h"
  8. #include "unit.h"
  9. #include "tools.h"
  10. void pcilib_clean_value(pcilib_t *ctx, pcilib_value_t *val) {
  11. if (!val) return;
  12. if (val->data) {
  13. free(val->data);
  14. val->data = NULL;
  15. }
  16. memset(val, 0, sizeof(pcilib_value_t));
  17. }
  18. int pcilib_copy_value(pcilib_t *ctx, pcilib_value_t *dst, const pcilib_value_t *src) {
  19. if (dst->type != PCILIB_TYPE_INVALID)
  20. pcilib_clean_value(ctx, dst);
  21. memcpy(dst, src, sizeof(pcilib_value_t));
  22. if ((src->size)&&(src->data)) {
  23. dst->data = malloc(src->size);
  24. if (!dst->data) {
  25. dst->type = PCILIB_TYPE_INVALID;
  26. return PCILIB_ERROR_MEMORY;
  27. }
  28. memcpy(dst->data, src->data, src->size);
  29. }
  30. return 0;
  31. }
  32. int pcilib_set_value_from_float(pcilib_t *ctx, pcilib_value_t *value, double fval) {
  33. pcilib_clean_value(ctx, value);
  34. value->type = PCILIB_TYPE_DOUBLE;
  35. value->fval = fval;
  36. return 0;
  37. }
  38. int pcilib_set_value_from_int(pcilib_t *ctx, pcilib_value_t *value, long ival) {
  39. pcilib_clean_value(ctx, value);
  40. value->type = PCILIB_TYPE_LONG;
  41. value->ival = ival;
  42. return 0;
  43. }
  44. int pcilib_set_value_from_register_value(pcilib_t *ctx, pcilib_value_t *value, pcilib_register_value_t regval) {
  45. return pcilib_set_value_from_int(ctx, value, regval);
  46. }
  47. int pcilib_set_value_from_static_string(pcilib_t *ctx, pcilib_value_t *value, const char *str) {
  48. pcilib_clean_value(ctx, value);
  49. value->type = PCILIB_TYPE_STRING;
  50. value->sval = str;
  51. return 0;
  52. }
  53. double pcilib_get_value_as_float(pcilib_t *ctx, const pcilib_value_t *val, int *ret) {
  54. int err;
  55. double res;
  56. pcilib_value_t copy = {0};
  57. err = pcilib_copy_value(ctx, &copy, val);
  58. if (err) {
  59. if (ret) *ret = err;
  60. return 0.;
  61. }
  62. err = pcilib_convert_value_type(ctx, &copy, PCILIB_TYPE_DOUBLE);
  63. if (err) {
  64. if (ret) *ret = err;
  65. return 0.;
  66. }
  67. if (ret) *ret = 0;
  68. res = copy.fval;
  69. pcilib_clean_value(ctx, &copy);
  70. return res;
  71. }
  72. long pcilib_get_value_as_int(pcilib_t *ctx, const pcilib_value_t *val, int *ret) {
  73. int err;
  74. long res;
  75. pcilib_value_t copy = {0};
  76. err = pcilib_copy_value(ctx, &copy, val);
  77. if (err) {
  78. if (ret) *ret = err;
  79. return 0;
  80. }
  81. err = pcilib_convert_value_type(ctx, &copy, PCILIB_TYPE_LONG);
  82. if (err) {
  83. if (ret) *ret = err;
  84. return 0;
  85. }
  86. if (ret) *ret = 0;
  87. res = copy.ival;
  88. pcilib_clean_value(ctx, &copy);
  89. return res;
  90. }
  91. pcilib_register_value_t pcilib_get_value_as_register_value(pcilib_t *ctx, const pcilib_value_t *val, int *ret) {
  92. int err;
  93. pcilib_register_value_t res;
  94. pcilib_value_t copy = {0};
  95. err = pcilib_copy_value(ctx, &copy, val);
  96. if (err) {
  97. if (ret) *ret = err;
  98. return 0.;
  99. }
  100. err = pcilib_convert_value_type(ctx, &copy, PCILIB_TYPE_LONG);
  101. if (err) {
  102. if (ret) *ret = err;
  103. return 0.;
  104. }
  105. if (ret) *ret = 0;
  106. res = copy.ival;
  107. pcilib_clean_value(ctx, &copy);
  108. return res;
  109. }
  110. /*
  111. double pcilib_value_get_float(pcilib_value_t *val) {
  112. pcilib_value_t copy;
  113. if (val->type == PCILIB_TYPE_DOUBLE)
  114. return val->fval;
  115. err = pcilib_copy_value(&copy, val);
  116. if (err) ???
  117. }
  118. long pcilib_value_get_int(pcilib_value_t *val) {
  119. }
  120. */
  121. int pcilib_convert_value_unit(pcilib_t *ctx, pcilib_value_t *val, const char *unit_name) {
  122. if (val->type == PCILIB_TYPE_INVALID) {
  123. pcilib_error("Can't convert uninitialized value");
  124. return PCILIB_ERROR_NOTINITIALIZED;
  125. }
  126. if ((val->type != PCILIB_TYPE_DOUBLE)&&(val->type != PCILIB_TYPE_LONG)) {
  127. pcilib_error("Can't convert value of type %u, only values with integer and float types can be converted to different units", val->type);
  128. return PCILIB_ERROR_INVALID_ARGUMENT;
  129. }
  130. if (!val->unit) {
  131. pcilib_error("Can't convert value with the unspecified unit");
  132. return PCILIB_ERROR_INVALID_ARGUMENT;
  133. }
  134. pcilib_unit_t unit = pcilib_find_unit_by_name(ctx, val->unit);
  135. if (unit == PCILIB_UNIT_INVALID) {
  136. pcilib_error("Can't convert unrecognized unit %s", val->unit);
  137. return PCILIB_ERROR_NOTFOUND;
  138. }
  139. return pcilib_transform_unit_by_name(ctx, unit_name, val);
  140. }
  141. int pcilib_convert_value_type(pcilib_t *ctx, pcilib_value_t *val, pcilib_value_type_t type) {
  142. if (val->type == PCILIB_TYPE_INVALID) {
  143. pcilib_error("Can't convert uninitialized value");
  144. return PCILIB_ERROR_NOTINITIALIZED;
  145. }
  146. switch (type) {
  147. case PCILIB_TYPE_STRING:
  148. switch (val->type) {
  149. case PCILIB_TYPE_STRING:
  150. return 0;
  151. case PCILIB_TYPE_DOUBLE:
  152. sprintf(val->str, (val->format?val->format:"%lf"), val->fval);
  153. val->format = NULL;
  154. break;
  155. case PCILIB_TYPE_LONG:
  156. sprintf(val->str, (val->format?val->format:"%li"), val->ival);
  157. val->format = NULL;
  158. break;
  159. default:
  160. return PCILIB_ERROR_NOTSUPPORTED;
  161. }
  162. val->sval = val->str;
  163. break;
  164. case PCILIB_TYPE_DOUBLE:
  165. switch (val->type) {
  166. case PCILIB_TYPE_STRING:
  167. if (sscanf(val->sval, "%lf", &val->fval) != 1) {
  168. pcilib_warning("Can't convert string (%s) to float", val->sval);
  169. return PCILIB_ERROR_INVALID_DATA;
  170. }
  171. val->format = NULL;
  172. break;
  173. case PCILIB_TYPE_DOUBLE:
  174. return 0;
  175. case PCILIB_TYPE_LONG:
  176. val->fval = val->ival;
  177. val->format = NULL;
  178. break;
  179. default:
  180. return PCILIB_ERROR_NOTSUPPORTED;
  181. }
  182. break;
  183. case PCILIB_TYPE_LONG:
  184. switch (val->type) {
  185. case PCILIB_TYPE_STRING:
  186. if (pcilib_isnumber(val->sval)) {
  187. if (sscanf(val->sval, "%li", &val->ival) != 1) {
  188. pcilib_warning("Can't convert string (%s) to int", val->sval);
  189. return PCILIB_ERROR_INVALID_DATA;
  190. }
  191. val->format = NULL;
  192. } else if (pcilib_isxnumber(val->sval)) {
  193. if (sscanf(val->sval, "%lx", &val->ival) != 1) {
  194. pcilib_warning("Can't convert string (%s) to int", val->sval);
  195. return PCILIB_ERROR_INVALID_DATA;
  196. }
  197. val->format = "0x%lx";
  198. } else {
  199. pcilib_warning("Can't convert string (%s) to int", val->sval);
  200. return PCILIB_ERROR_INVALID_DATA;
  201. }
  202. break;
  203. case PCILIB_TYPE_DOUBLE:
  204. val->ival = round(val->fval);
  205. val->format = NULL;
  206. break;
  207. case PCILIB_TYPE_LONG:
  208. return 0;
  209. default:
  210. return PCILIB_ERROR_NOTSUPPORTED;
  211. }
  212. break;
  213. default:
  214. return PCILIB_ERROR_NOTSUPPORTED;
  215. }
  216. val->type = type;
  217. return 0;
  218. }