mirror of
https://gitee.com/xiaohuolufeihua/bizhang_-obav.git
synced 2026-05-22 09:28:58 +00:00
Add support for setting and exporting parameters.
This commit is contained in:
@@ -6,10 +6,13 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <err.h>
|
||||
|
||||
#include "param.h"
|
||||
#include "systemlib/param/param.h"
|
||||
#include "systemlib/uthash/utarray.h"
|
||||
#include "systemlib/bson/bson.h"
|
||||
|
||||
/**
|
||||
* Array of static parameter info.
|
||||
@@ -19,12 +22,78 @@ static const struct param_info_s *param_info_base = (struct param_info_s *)&__pa
|
||||
static const struct param_info_s *param_info_limit = (struct param_info_s *)&__param_end;
|
||||
#define param_info_count ((unsigned)(param_info_limit - param_info_base))
|
||||
|
||||
/**
|
||||
* Storage for modified parameters.
|
||||
*/
|
||||
struct param_wbuf_s
|
||||
{
|
||||
param_t param;
|
||||
union param_value_u val;
|
||||
bool unsaved;
|
||||
};
|
||||
|
||||
UT_icd param_icd = {sizeof(struct param_wbuf_s), NULL, NULL, NULL};
|
||||
UT_array *param_values;
|
||||
|
||||
static void
|
||||
param_lock(void)
|
||||
{
|
||||
/* XXX */
|
||||
}
|
||||
|
||||
static void
|
||||
param_unlock(void)
|
||||
{
|
||||
/* XXX */
|
||||
}
|
||||
|
||||
static void
|
||||
param_assert_locked(void)
|
||||
{
|
||||
/* XXX */
|
||||
}
|
||||
|
||||
static bool
|
||||
handle_in_range(param_t handle)
|
||||
{
|
||||
return (handle < param_info_count);
|
||||
}
|
||||
|
||||
static int
|
||||
param_compare_values(const void *a, const void *b)
|
||||
{
|
||||
struct param_wbuf_s *pa = (struct param_wbuf_s *)a;
|
||||
struct param_wbuf_s *pb = (struct param_wbuf_s *)b;
|
||||
|
||||
if (pa->param < pb->param)
|
||||
return -1;
|
||||
if (pa->param > pb->param)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct param_wbuf_s *
|
||||
param_find_changed(param_t param)
|
||||
{
|
||||
struct param_wbuf_s *s = NULL;
|
||||
|
||||
param_assert_locked();
|
||||
|
||||
if (param_values != NULL) {
|
||||
#if 0 /* utarray_find requires bsearch, not available */
|
||||
struct param_wbuf_s key;
|
||||
key.param = param;
|
||||
s = utarray_find(param_values, &key, param_compare_values);
|
||||
#else
|
||||
while ((s = (struct param_wbuf_s *)utarray_next(param_values, s)) != NULL) {
|
||||
if (s->param == param)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
param_t
|
||||
param_find(const char *name)
|
||||
{
|
||||
@@ -39,8 +108,17 @@ param_find(const char *name)
|
||||
return PARAM_INVALID;
|
||||
}
|
||||
|
||||
enum
|
||||
param_type_e param_type(param_t param)
|
||||
const char *
|
||||
param_name(param_t param)
|
||||
{
|
||||
if (handle_in_range(param))
|
||||
return param_info_base[param].name;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
enum param_type_e
|
||||
param_type(param_t param)
|
||||
{
|
||||
if (handle_in_range(param))
|
||||
return param_info_base[param].type;
|
||||
@@ -51,7 +129,6 @@ param_type_e param_type(param_t param)
|
||||
size_t
|
||||
param_size(param_t param)
|
||||
{
|
||||
|
||||
if (handle_in_range(param)) {
|
||||
switch (param_info_base[param].type) {
|
||||
case PARAM_TYPE_INT32:
|
||||
@@ -72,39 +149,193 @@ param_size(param_t param)
|
||||
int
|
||||
param_get(param_t param, void *val)
|
||||
{
|
||||
int result = -1;
|
||||
|
||||
param_lock();
|
||||
|
||||
if (handle_in_range(param)) {
|
||||
|
||||
struct param_wbuf_s *s = param_find_changed(param);
|
||||
const union param_value_u *v;
|
||||
|
||||
/* work out whether we're fetching the default or a written value */
|
||||
if (s != NULL) {
|
||||
v = &s->val;
|
||||
} else {
|
||||
v = ¶m_info_base[param].val;
|
||||
}
|
||||
|
||||
/* XXX look for updated value stored elsewhere */
|
||||
|
||||
switch (param_info_base[param].type) {
|
||||
case PARAM_TYPE_INT32:
|
||||
*(int32_t *)val = param_info_base[param].i;
|
||||
return 0;
|
||||
*(int32_t *)val = v->i;
|
||||
result = 0;
|
||||
break;
|
||||
|
||||
case PARAM_TYPE_FLOAT:
|
||||
*(float *)val = param_info_base[param].f;
|
||||
return 0;
|
||||
*(float *)val = v->f;
|
||||
result = 0;
|
||||
break;
|
||||
|
||||
case PARAM_TYPE_STRUCT ... PARAM_TYPE_STRUCT_MAX:
|
||||
memcpy(val, param_info_base[param].p, param_size(param));
|
||||
return 0;
|
||||
*(void **)val = v->p;
|
||||
result = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return -1;
|
||||
|
||||
param_unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
param_set(param_t param, void *val)
|
||||
{
|
||||
int result = -1;
|
||||
|
||||
param_lock();
|
||||
|
||||
if (param_values == NULL)
|
||||
utarray_new(param_values, ¶m_icd);
|
||||
if (param_values == NULL)
|
||||
goto out;
|
||||
|
||||
if (handle_in_range(param)) {
|
||||
|
||||
/* XXX maintain list of changed values */
|
||||
struct param_wbuf_s *s = param_find_changed(param);
|
||||
|
||||
if (s == NULL) {
|
||||
|
||||
/* construct a new parameter */
|
||||
struct param_wbuf_s buf = { .param = param };
|
||||
|
||||
/* add it to the array and sort */
|
||||
utarray_push_back(param_values, &buf);
|
||||
utarray_sort(param_values, param_compare_values);
|
||||
|
||||
/* find it after sorting */
|
||||
s = param_find_changed(param);
|
||||
}
|
||||
|
||||
/* update the changed value */
|
||||
switch (param_info_base[param].type) {
|
||||
case PARAM_TYPE_INT32:
|
||||
s->val.i = *(int32_t *)val;
|
||||
break;
|
||||
|
||||
case PARAM_TYPE_FLOAT:
|
||||
s->val.f = *(float *)val;
|
||||
break;
|
||||
|
||||
case PARAM_TYPE_STRUCT ... PARAM_TYPE_STRUCT_MAX:
|
||||
s->val.p = *(void **)val;
|
||||
break;
|
||||
|
||||
default:
|
||||
goto out;
|
||||
}
|
||||
s->unsaved = true;
|
||||
|
||||
result = 0;
|
||||
}
|
||||
return -1;
|
||||
|
||||
out:
|
||||
param_unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
param_export(const char *filename, bool only_unsaved)
|
||||
{
|
||||
struct param_wbuf_s *s;
|
||||
bson b[1];
|
||||
int result = -1;
|
||||
|
||||
param_lock();
|
||||
|
||||
bson_init(b);
|
||||
|
||||
while ((s = (struct param_wbuf_s *)utarray_next(param_values, s)) != NULL) {
|
||||
const struct param_info_s *is = ¶m_info_base[s->param];
|
||||
|
||||
/*
|
||||
* if we are only saving values changed since last save, and this
|
||||
* one hasn't, then skip it
|
||||
*/
|
||||
if (only_unsaved & !s->unsaved)
|
||||
continue;
|
||||
s->unsaved = false;
|
||||
|
||||
switch (is->type) {
|
||||
case PARAM_TYPE_INT32:
|
||||
if (bson_append_int(b, is->name, s->val.i) != BSON_OK)
|
||||
goto out;
|
||||
break;
|
||||
|
||||
case PARAM_TYPE_FLOAT:
|
||||
if (bson_append_double(b, is->name, s->val.f) != BSON_OK)
|
||||
goto out;
|
||||
break;
|
||||
|
||||
case PARAM_TYPE_STRUCT ... PARAM_TYPE_STRUCT_MAX:
|
||||
if (bson_append_binary(b,
|
||||
is->name,
|
||||
is->type,
|
||||
is->val.p,
|
||||
is->type - PARAM_TYPE_STRUCT) != BSON_OK)
|
||||
goto out;
|
||||
break;
|
||||
default:
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
result = 0;
|
||||
|
||||
out:
|
||||
param_unlock();
|
||||
|
||||
if (result == 0) {
|
||||
bson_finish(b);
|
||||
bson_print(b);
|
||||
|
||||
warnx("object is %d bytes", bson_buffer_size(b));
|
||||
|
||||
if (filename != NULL) {
|
||||
int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
|
||||
int siz = bson_buffer_size(b);
|
||||
int len = write(fd, bson_data(b), siz);
|
||||
close(fd);
|
||||
if (len != siz)
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
bson_destroy(b);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
param_import(const char *filename)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
param_foreach(void (*func)(void *arg, param_t param), void *arg, bool only_changed)
|
||||
{
|
||||
param_t param;
|
||||
|
||||
for (param = 0; handle_in_range(param); param++) {
|
||||
|
||||
/* if requested, skip unchanged values */
|
||||
if (only_changed && (param_find_changed(param) == NULL))
|
||||
continue;
|
||||
|
||||
func(arg, param);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user