123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- #define _POSIX_C_SOURCE 200809L
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
- #include "pcilib.h"
- #include "value.h"
- #include "error.h"
- #include "unit.h"
- #include "tools.h"
- void pcilib_clean_value(pcilib_t *ctx, pcilib_value_t *val) {
- if (!val) return;
- if (val->data) {
- free(val->data);
- val->data = NULL;
- }
- memset(val, 0, sizeof(pcilib_value_t));
- }
- int pcilib_copy_value(pcilib_t *ctx, pcilib_value_t *dst, const pcilib_value_t *src) {
- if (dst->type != PCILIB_TYPE_INVALID)
- pcilib_clean_value(ctx, dst);
- memcpy(dst, src, sizeof(pcilib_value_t));
- if ((src->size)&&(src->data)) {
- dst->data = malloc(src->size);
- if (!dst->data) {
- dst->type = PCILIB_TYPE_INVALID;
- return PCILIB_ERROR_MEMORY;
- }
- memcpy(dst->data, src->data, src->size);
- }
- return 0;
- }
- int pcilib_set_value_from_float(pcilib_t *ctx, pcilib_value_t *value, double fval) {
- pcilib_clean_value(ctx, value);
- value->type = PCILIB_TYPE_DOUBLE;
- value->fval = fval;
- return 0;
- }
- int pcilib_set_value_from_int(pcilib_t *ctx, pcilib_value_t *value, long ival) {
- pcilib_clean_value(ctx, value);
- value->type = PCILIB_TYPE_LONG;
- value->ival = ival;
- return 0;
- }
- int pcilib_set_value_from_register_value(pcilib_t *ctx, pcilib_value_t *value, pcilib_register_value_t regval) {
- return pcilib_set_value_from_int(ctx, value, regval);
- }
- int pcilib_set_value_from_static_string(pcilib_t *ctx, pcilib_value_t *value, const char *str) {
- pcilib_clean_value(ctx, value);
- value->type = PCILIB_TYPE_STRING;
- value->sval = str;
- return 0;
- }
- int pcilib_set_value_from_string(pcilib_t *ctx, pcilib_value_t *value, const char *str) {
- size_t len;
- pcilib_clean_value(ctx, value);
- len = strlen(str) + 1;
- if (len < sizeof(value->str)) {
- memcpy(value->str, str, len);
- value->sval = value->str;
- } else {
- value->data = (void*)strdup(str);
- if (!value->data) return PCILIB_ERROR_MEMORY;
- value->size = strlen(str) + 1;
- value->sval = value->data;
- }
- value->type = PCILIB_TYPE_STRING;
- return 0;
- }
- double pcilib_get_value_as_float(pcilib_t *ctx, const pcilib_value_t *val, int *ret) {
- int err;
- double res;
- pcilib_value_t copy = {0};
- err = pcilib_copy_value(ctx, ©, val);
- if (err) {
- if (ret) *ret = err;
- return 0.;
- }
- err = pcilib_convert_value_type(ctx, ©, PCILIB_TYPE_DOUBLE);
- if (err) {
- if (ret) *ret = err;
- return 0.;
- }
- if (ret) *ret = 0;
- res = copy.fval;
- pcilib_clean_value(ctx, ©);
- return res;
- }
- long pcilib_get_value_as_int(pcilib_t *ctx, const pcilib_value_t *val, int *ret) {
- int err;
- long res;
- pcilib_value_t copy = {0};
- err = pcilib_copy_value(ctx, ©, val);
- if (err) {
- if (ret) *ret = err;
- return 0;
- }
- err = pcilib_convert_value_type(ctx, ©, PCILIB_TYPE_LONG);
- if (err) {
- if (ret) *ret = err;
- return 0;
- }
- if (ret) *ret = 0;
- res = copy.ival;
- pcilib_clean_value(ctx, ©);
- return res;
- }
- pcilib_register_value_t pcilib_get_value_as_register_value(pcilib_t *ctx, const pcilib_value_t *val, int *ret) {
- int err;
- pcilib_register_value_t res;
- pcilib_value_t copy = {0};
- err = pcilib_copy_value(ctx, ©, val);
- if (err) {
- if (ret) *ret = err;
- return 0.;
- }
- err = pcilib_convert_value_type(ctx, ©, PCILIB_TYPE_LONG);
- if (err) {
- if (ret) *ret = err;
- return 0.;
- }
- if (ret) *ret = 0;
- res = copy.ival;
- if (copy.ival < 0)
- pcilib_warning("Data corruption while converting negative polymorph value (%li) to the register type, result %u", copy.ival, res);
- pcilib_clean_value(ctx, ©);
- return res;
- }
- /*
- double pcilib_value_get_float(pcilib_value_t *val) {
- pcilib_value_t copy;
- if (val->type == PCILIB_TYPE_DOUBLE)
- return val->fval;
- err = pcilib_copy_value(©, val);
- if (err) ???
- }
- long pcilib_value_get_int(pcilib_value_t *val) {
- }
- */
- int pcilib_convert_value_unit(pcilib_t *ctx, pcilib_value_t *val, const char *unit_name) {
- if (val->type == PCILIB_TYPE_INVALID) {
- pcilib_error("Can't convert uninitialized value");
- return PCILIB_ERROR_NOTINITIALIZED;
- }
- if ((val->type != PCILIB_TYPE_DOUBLE)&&(val->type != PCILIB_TYPE_LONG)) {
- pcilib_error("Can't convert value of type %u, only values with integer and float types can be converted to different units", val->type);
- return PCILIB_ERROR_INVALID_ARGUMENT;
- }
- if (!val->unit) {
- pcilib_error("Can't convert value with the unspecified unit");
- return PCILIB_ERROR_INVALID_ARGUMENT;
- }
- pcilib_unit_t unit = pcilib_find_unit_by_name(ctx, val->unit);
- if (unit == PCILIB_UNIT_INVALID) {
- pcilib_error("Can't convert unrecognized unit %s", val->unit);
- return PCILIB_ERROR_NOTFOUND;
- }
- return pcilib_transform_unit_by_name(ctx, unit_name, val);
- }
- int pcilib_convert_value_type(pcilib_t *ctx, pcilib_value_t *val, pcilib_value_type_t type) {
- if (val->type == PCILIB_TYPE_INVALID) {
- pcilib_error("Can't convert uninitialized value");
- return PCILIB_ERROR_NOTINITIALIZED;
- }
- switch (type) {
- case PCILIB_TYPE_STRING:
- switch (val->type) {
- case PCILIB_TYPE_STRING:
- return 0;
- case PCILIB_TYPE_DOUBLE:
- sprintf(val->str, (val->format?val->format:"%lf"), val->fval);
- val->format = NULL;
- break;
- case PCILIB_TYPE_LONG:
- sprintf(val->str, (val->format?val->format:"%li"), val->ival);
- val->format = NULL;
- break;
- default:
- return PCILIB_ERROR_NOTSUPPORTED;
- }
- val->sval = val->str;
- break;
- case PCILIB_TYPE_DOUBLE:
- switch (val->type) {
- case PCILIB_TYPE_STRING:
- if (sscanf(val->sval, "%lf", &val->fval) != 1) {
- pcilib_warning("Can't convert string (%s) to float", val->sval);
- return PCILIB_ERROR_INVALID_DATA;
- }
- val->format = NULL;
- break;
- case PCILIB_TYPE_DOUBLE:
- return 0;
- case PCILIB_TYPE_LONG:
- val->fval = val->ival;
- val->format = NULL;
- break;
- default:
- return PCILIB_ERROR_NOTSUPPORTED;
- }
- break;
- case PCILIB_TYPE_LONG:
- switch (val->type) {
- case PCILIB_TYPE_STRING:
- if (pcilib_isnumber(val->sval)) {
- if (sscanf(val->sval, "%li", &val->ival) != 1) {
- pcilib_warning("Can't convert string (%s) to int", val->sval);
- return PCILIB_ERROR_INVALID_DATA;
- }
- val->format = NULL;
- } else if (pcilib_isxnumber(val->sval)) {
- if (sscanf(val->sval, "%lx", &val->ival) != 1) {
- pcilib_warning("Can't convert string (%s) to int", val->sval);
- return PCILIB_ERROR_INVALID_DATA;
- }
- val->format = "0x%lx";
- } else {
- pcilib_warning("Can't convert string (%s) to int", val->sval);
- return PCILIB_ERROR_INVALID_DATA;
- }
- break;
- case PCILIB_TYPE_DOUBLE:
- if (val->fval != round(val->fval))
- pcilib_info("Precision is lost while converting float value %lf to integer %.0lf", val->fval, round(val->fval));
- val->ival = round(val->fval);
- val->format = NULL;
- break;
- case PCILIB_TYPE_LONG:
- return 0;
- default:
- return PCILIB_ERROR_NOTSUPPORTED;
- }
- break;
- default:
- return PCILIB_ERROR_NOTSUPPORTED;
- }
- val->type = type;
- return 0;
- }
|