PyObject *py_dec_options, *py_dec_optkeys, *py_di_options, *py_optval;
PyObject *py_optlist, *py_classval;
Py_UNICODE *py_ustr;
+ GVariant *value;
unsigned long long int val_ull;
+ gint64 val_int;
int num_optkeys, ret, size, i;
- char *key, *value;
+ const char *val_str;
+ char *dbg, *key;
if (!PyObject_HasAttrString(di->decoder->py_dec, "options")) {
/* Decoder has no options. */
}
if ((value = g_hash_table_lookup(options, key))) {
+ dbg = g_variant_print(value, TRUE);
+ srd_dbg("got option '%s' = %s", key, dbg);
+ g_free(dbg);
/* An override for this option was provided. */
if (PyUnicode_Check(py_classval)) {
- if (!(py_optval = PyUnicode_FromString(value))) {
+ if (!g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) {
+ srd_err("Option '%s' requires a string value.", key);
+ goto err_out;
+ }
+ val_str = g_variant_get_string(value, NULL);
+ if (!(py_optval = PyUnicode_FromString(val_str))) {
/* Some UTF-8 encoding error. */
PyErr_Clear();
+ srd_err("Option '%s' requires a UTF-8 string value.", key);
goto err_out;
}
} else if (PyLong_Check(py_classval)) {
- if (!(py_optval = PyLong_FromString(value, NULL, 0))) {
+ if (!g_variant_is_of_type(value, G_VARIANT_TYPE_INT64)) {
+ srd_err("Option '%s' requires an integer value.", key);
+ goto err_out;
+ }
+ val_int = g_variant_get_int64(value);
+ if (!(py_optval = PyLong_FromLong(val_int))) {
/* ValueError Exception */
PyErr_Clear();
- srd_err("Option %s has invalid value "
- "%s: expected integer.",
- key, value);
+ srd_err("Option '%s' has invalid integer value.", key);
goto err_out;
}
}
SRD_API int srd_inst_probe_set_all(struct srd_decoder_inst *di,
GHashTable *new_probes)
{
+ GVariant *probe_val;
GList *l;
GSList *sl;
struct srd_probe *p;
int *new_probemap, new_probenum;
- char *probe_id, *probenum_str;
+ char *probe_id;
int i, num_required_probes;
srd_dbg("set probes called for instance %s with list of %d probes",
for (l = g_hash_table_get_keys(new_probes); l; l = l->next) {
probe_id = l->data;
- probenum_str = g_hash_table_lookup(new_probes, probe_id);
- if (!probenum_str) {
+ probe_val= g_hash_table_lookup(new_probes, probe_id);
+ if (!g_variant_is_of_type(probe_val, G_VARIANT_TYPE_INT32)) {
/* Probe name was specified without a value. */
srd_err("No probe number was specified for %s.",
- probe_id);
+ probe_id);
g_free(new_probemap);
return SRD_ERR_ARG;
}
- new_probenum = strtol(probenum_str, NULL, 10);
+ new_probenum = g_variant_get_int32(probe_val);
if (!(sl = g_slist_find_custom(di->decoder->probes, probe_id,
(GCompareFunc)compare_probe_id))) {
/* Fall back on optional probes. */
if (!(sl = g_slist_find_custom(di->decoder->opt_probes,
probe_id, (GCompareFunc) compare_probe_id))) {
srd_err("Protocol decoder %s has no probe "
- "'%s'.", di->decoder->name, probe_id);
+ "'%s'.", di->decoder->name, probe_id);
g_free(new_probemap);
return SRD_ERR_ARG;
}
return ret;
}
+static int get_options(struct srd_decoder *d)
+{
+ PyObject *py_opts, *py_keys, *py_values, *py_val, *py_desc, *py_default;
+ Py_ssize_t i;
+ struct srd_decoder_option *o;
+ gint64 def_long;
+ int num_keys, overflow, ret;
+ char *key, *def_str;
+
+ ret = SRD_ERR_PYTHON;
+ key = NULL;
+
+ if (!PyObject_HasAttrString(d->py_dec, "options"))
+ /* That's fine. */
+ return SRD_OK;
+
+ /* If present, options must be a dictionary. */
+ py_opts = PyObject_GetAttrString(d->py_dec, "options");
+ if (!PyDict_Check(py_opts)) {
+ srd_err("Protocol decoder %s options attribute is not "
+ "a dictionary.", d->name);
+ goto err_out;
+ }
+
+ py_keys = PyDict_Keys(py_opts);
+ py_values = PyDict_Values(py_opts);
+ num_keys = PyList_Size(py_keys);
+ for (i = 0; i < num_keys; i++) {
+ py_str_as_str(PyList_GetItem(py_keys, i), &key);
+ srd_dbg("option '%s'", key);
+ py_val = PyList_GetItem(py_values, i);
+ if (!PyList_Check(py_val) || PyList_Size(py_val) != 2) {
+ srd_err("Protocol decoder %s option '%s' value must be "
+ "a list with two elements.", d->name, key);
+ goto err_out;
+ }
+ py_desc = PyList_GetItem(py_val, 0);
+ if (!PyUnicode_Check(py_desc)) {
+ srd_err("Protocol decoder %s option '%s' has no "
+ "description.", d->name, key);
+ goto err_out;
+ }
+ py_default = PyList_GetItem(py_val, 1);
+ if (!PyUnicode_Check(py_default) && !PyLong_Check(py_default)) {
+ srd_err("Protocol decoder %s option '%s' has default "
+ "of unsupported type '%s'.", d->name, key,
+ Py_TYPE(py_default)->tp_name);
+ goto err_out;
+ }
+ if (!(o = g_try_malloc(sizeof(struct srd_decoder_option)))) {
+ srd_err("option malloc failed");
+ goto err_out;
+ }
+ o->id = g_strdup(key);
+ py_str_as_str(py_desc, &o->desc);
+ if (PyUnicode_Check(py_default)) {
+ /* UTF-8 string */
+ py_str_as_str(py_default, &def_str);
+ o->def = g_variant_new_string(def_str);
+ g_free(def_str);
+ } else {
+ /* Long */
+ def_long = PyLong_AsLongAndOverflow(py_default, &overflow);
+ if (overflow) {
+ /* Value is < LONG_MIN or > LONG_MAX */
+ PyErr_Clear();
+ srd_err("Protocol decoder %s option '%s' has "
+ "invalid default value.", d->name, key);
+ goto err_out;
+ }
+ o->def = g_variant_new_int64(def_long);
+ }
+ g_variant_ref_sink(o->def);
+ d->options = g_slist_append(d->options, o);
+ }
+ Py_DecRef(py_keys);
+ Py_DecRef(py_values);
+
+ ret = SRD_OK;
+
+err_out:
+ Py_XDECREF(py_opts);
+ g_free(key);
+
+ return ret;
+}
+
/**
* Load a protocol decoder module into the embedded Python interpreter.
*
}
Py_CLEAR(py_method);
- /* If present, options must be a dictionary. */
- if (PyObject_HasAttrString(d->py_dec, "options")) {
- py_attr = PyObject_GetAttrString(d->py_dec, "options");
- if (!PyDict_Check(py_attr)) {
- srd_err("Protocol decoder %s options attribute is not "
- "a dictionary.", d->name);
- Py_DecRef(py_attr);
- goto err_out;
- }
- Py_DecRef(py_attr);
- }
+ if (get_options(d) != SRD_OK)
+ goto err_out;
/* Check and import required probes. */
if (get_probes(d, "probes", &d->probes) != SRD_OK)
*/
SRD_API int srd_decoder_unload(struct srd_decoder *dec)
{
+ struct srd_decoder_option *o;
+ GSList *l;
+
srd_dbg("Unloading protocol decoder '%s'.", dec->name);
/*
*/
srd_inst_free_all(NULL);
+ for (l = dec->options; l; l = l->next) {
+ o = l->data;
+ g_free(o->id);
+ g_free(o->desc);
+ g_variant_unref(o->def);
+ g_free(o);
+ }
+ g_slist_free(dec->options);
+
free_probes(dec->probes);
free_probes(dec->opt_probes);
g_free(dec->id);