]> sigrok.org Git - libsigrokdecode.git/blobdiff - type_decoder.c
type_decoder.c: Fix a compiler warning (-Wswitch-default).
[libsigrokdecode.git] / type_decoder.c
index f2033776e89e8e4ccf42330e19f1e8ab826aaa8c..e69b3c4e0b11e32f870bf35861a2a0368e09c430 100644 (file)
@@ -40,6 +40,15 @@ static const char *output_type_name(unsigned int idx)
        return names[MIN(idx, G_N_ELEMENTS(names) - 1)];
 }
 
+static void release_annotation(struct srd_proto_data_annotation *pda)
+{
+       if (!pda)
+               return;
+       if (pda->ann_text)
+               g_strfreev(pda->ann_text);
+       g_free(pda);
+}
+
 static int convert_annotation(struct srd_decoder_inst *di, PyObject *obj,
                struct srd_proto_data *pdata)
 {
@@ -112,6 +121,14 @@ err:
        return SRD_ERR_PYTHON;
 }
 
+static void release_binary(struct srd_proto_data_binary *pdb)
+{
+       if (!pdb)
+               return;
+       g_free((void *)pdb->data);
+       g_free(pdb);
+}
+
 static int convert_binary(struct srd_decoder_inst *di, PyObject *obj,
                struct srd_proto_data *pdata)
 {
@@ -168,16 +185,18 @@ static int convert_binary(struct srd_decoder_inst *di, PyObject *obj,
                goto err;
        }
 
-       pdb = g_malloc(sizeof(struct srd_proto_data_binary));
        if (PyBytes_AsStringAndSize(py_tmp, &buf, &size) == -1)
                goto err;
 
        PyGILState_Release(gstate);
 
+       pdb = g_malloc(sizeof(struct srd_proto_data_binary));
        pdb->bin_class = bin_class;
        pdb->size = size;
-       if (!(pdb->data = g_try_malloc(pdb->size)))
+       if (!(pdb->data = g_try_malloc(pdb->size))) {
+               g_free(pdb);
                return SRD_ERR_MALLOC;
+       }
        memcpy((void *)pdb->data, (const void *)buf, pdb->size);
        pdata->data = pdb;
 
@@ -229,18 +248,27 @@ err:
        return SRD_ERR_PYTHON;
 }
 
+static void release_meta(GVariant *gvar)
+{
+       if (!gvar)
+               return;
+       g_variant_unref(gvar);
+}
+
 static PyObject *Decoder_put(PyObject *self, PyObject *args)
 {
        GSList *l;
        PyObject *py_data, *py_res;
        struct srd_decoder_inst *di, *next_di;
        struct srd_pd_output *pdo;
-       struct srd_proto_data *pdata;
+       struct srd_proto_data pdata;
        uint64_t start_sample, end_sample;
        int output_id;
        struct srd_pd_callback *cb;
        PyGILState_STATE gstate;
 
+       py_data = NULL;
+
        gstate = PyGILState_Ensure();
 
        if (!(di = srd_inst_find_by_obj(NULL, self))) {
@@ -270,23 +298,24 @@ static PyObject *Decoder_put(PyObject *self, PyObject *args)
                 di->inst_id, start_sample, end_sample,
                 output_type_name(pdo->output_type), output_id);
 
-       pdata = g_malloc0(sizeof(struct srd_proto_data));
-       pdata->start_sample = start_sample;
-       pdata->end_sample = end_sample;
-       pdata->pdo = pdo;
+       pdata.start_sample = start_sample;
+       pdata.end_sample = end_sample;
+       pdata.pdo = pdo;
+       pdata.data = NULL;
 
        switch (pdo->output_type) {
        case SRD_OUTPUT_ANN:
                /* Annotations are only fed to callbacks. */
                if ((cb = srd_pd_output_callback_find(di->sess, pdo->output_type))) {
                        /* Convert from PyDict to srd_proto_data_annotation. */
-                       if (convert_annotation(di, py_data, pdata) != SRD_OK) {
+                       if (convert_annotation(di, py_data, &pdata) != SRD_OK) {
                                /* An error was already logged. */
                                break;
                        }
                        Py_BEGIN_ALLOW_THREADS
-                       cb->cb(pdata, cb->cb_data);
+                       cb->cb(&pdata, cb->cb_data);
                        Py_END_ALLOW_THREADS
+                       release_annotation(pdata.data);
                }
                break;
        case SRD_OUTPUT_PYTHON:
@@ -305,32 +334,34 @@ static PyObject *Decoder_put(PyObject *self, PyObject *args)
                if ((cb = srd_pd_output_callback_find(di->sess, pdo->output_type))) {
                        /* Frontends aren't really supposed to get Python
                         * callbacks, but it's useful for testing. */
-                       pdata->data = py_data;
-                       cb->cb(pdata, cb->cb_data);
+                       pdata.data = py_data;
+                       cb->cb(&pdata, cb->cb_data);
                }
                break;
        case SRD_OUTPUT_BINARY:
                if ((cb = srd_pd_output_callback_find(di->sess, pdo->output_type))) {
                        /* Convert from PyDict to srd_proto_data_binary. */
-                       if (convert_binary(di, py_data, pdata) != SRD_OK) {
+                       if (convert_binary(di, py_data, &pdata) != SRD_OK) {
                                /* An error was already logged. */
                                break;
                        }
                        Py_BEGIN_ALLOW_THREADS
-                       cb->cb(pdata, cb->cb_data);
+                       cb->cb(&pdata, cb->cb_data);
                        Py_END_ALLOW_THREADS
+                       release_binary(pdata.data);
                }
                break;
        case SRD_OUTPUT_META:
                if ((cb = srd_pd_output_callback_find(di->sess, pdo->output_type))) {
                        /* Annotations need converting from PyObject. */
-                       if (convert_meta(pdata, py_data) != SRD_OK) {
+                       if (convert_meta(&pdata, py_data) != SRD_OK) {
                                /* An exception was already set up. */
                                break;
                        }
                        Py_BEGIN_ALLOW_THREADS
-                       cb->cb(pdata, cb->cb_data);
+                       cb->cb(&pdata, cb->cb_data);
                        Py_END_ALLOW_THREADS
+                       release_meta(pdata.data);
                }
                break;
        default:
@@ -341,8 +372,6 @@ static PyObject *Decoder_put(PyObject *self, PyObject *args)
 
        PyGILState_Release(gstate);
 
-       g_free(pdata);
-
        Py_RETURN_NONE;
 
 err:
@@ -363,6 +392,9 @@ static PyObject *Decoder_register(PyObject *self, PyObject *args,
        char *proto_id, *meta_name, *meta_descr;
        char *keywords[] = {"output_type", "proto_id", "meta", NULL};
        PyGILState_STATE gstate;
+       gboolean is_meta;
+       GSList *l;
+       struct srd_pd_output *cmp;
 
        gstate = PyGILState_Ensure();
 
@@ -385,7 +417,8 @@ static PyObject *Decoder_register(PyObject *self, PyObject *args,
        }
 
        /* Check if the meta value's type is supported. */
-       if (output_type == SRD_OUTPUT_META) {
+       is_meta = output_type == SRD_OUTPUT_META;
+       if (is_meta) {
                if (meta_type_py == &PyLong_Type)
                        meta_type_gv = G_VARIANT_TYPE_INT64;
                else if (meta_type_py == &PyFloat_Type)
@@ -396,6 +429,28 @@ static PyObject *Decoder_register(PyObject *self, PyObject *args,
                }
        }
 
+       pdo = NULL;
+       for (l = di->pd_output; l; l = l->next) {
+               cmp = l->data;
+               if (cmp->output_type != output_type)
+                       continue;
+               if (strcmp(cmp->proto_id, proto_id) != 0)
+                       continue;
+               if (is_meta && cmp->meta_type != meta_type_gv)
+                       continue;
+               if (is_meta && strcmp(cmp->meta_name, meta_name) != 0)
+                       continue;
+               if (is_meta && strcmp(cmp->meta_descr, meta_descr) != 0)
+                       continue;
+               pdo = cmp;
+               break;
+       }
+       if (pdo) {
+               py_new_output_id = Py_BuildValue("i", pdo->pdo_id);
+               PyGILState_Release(gstate);
+               return py_new_output_id;
+       }
+
        srd_dbg("Instance %s creating new output type %d for %s.",
                di->inst_id, output_type, proto_id);
 
@@ -441,6 +496,8 @@ static int get_term_type(const char *v)
                return SRD_TERM_EITHER_EDGE;
        case 'n':
                return SRD_TERM_NO_EDGE;
+       default:
+               return -1;
        }
 
        return -1;
@@ -464,14 +521,13 @@ static PyObject *get_current_pinvalues(const struct srd_decoder_inst *di)
        PyObject *py_pinvalues;
        PyGILState_STATE gstate;
 
-       gstate = PyGILState_Ensure();
-
        if (!di) {
                srd_err("Invalid decoder instance.");
-               PyGILState_Release(gstate);
                return NULL;
        }
 
+       gstate = PyGILState_Ensure();
+
        py_pinvalues = PyTuple_New(di->dec_num_channels);
 
        for (i = 0; i < di->dec_num_channels; i++) {
@@ -532,7 +588,7 @@ static int create_term_list(PyObject *py_dict, GSList **term_list)
                                srd_err("Failed to get the value.");
                                goto err;
                        }
-                       term = g_malloc0(sizeof(struct srd_term));
+                       term = g_malloc(sizeof(struct srd_term));
                        term->type = get_term_type(term_str);
                        term->channel = PyLong_AsLong(py_key);
                        g_free(term_str);
@@ -543,7 +599,7 @@ static int create_term_list(PyObject *py_dict, GSList **term_list)
                                srd_err("Failed to get number of samples to skip.");
                                goto err;
                        }
-                       term = g_malloc0(sizeof(struct srd_term));
+                       term = g_malloc(sizeof(struct srd_term));
                        term->type = SRD_TERM_SKIP;
                        term->num_samples_to_skip = num_samples_to_skip;
                        term->num_samples_already_skipped = 0;
@@ -706,7 +762,7 @@ static int set_skip_condition(struct srd_decoder_inst *di, uint64_t count)
        GSList *term_list;
 
        condition_list_free(di);
-       term = g_malloc0(sizeof(*term));
+       term = g_malloc(sizeof(*term));
        term->type = SRD_TERM_SKIP;
        term->num_samples_to_skip = count;
        term->num_samples_already_skipped = 0;
@@ -781,7 +837,9 @@ static PyObject *Decoder_wait(PyObject *self, PyObject *args)
                 * while the termination request still gets signalled.
                 */
                found_match = FALSE;
-               ret = process_samples_until_condition_match(di, &found_match);
+
+               /* Ignore return value for now, should never be negative. */
+               (void)process_samples_until_condition_match(di, &found_match);
 
                Py_END_ALLOW_THREADS
 
@@ -800,7 +858,7 @@ static PyObject *Decoder_wait(PyObject *self, PyObject *args)
                        } else {
                                PyObject_SetAttrString(di->py_inst, "matched", Py_None);
                        }
-       
+
                        py_pinvalues = get_current_pinvalues(di);
 
                        g_mutex_unlock(&di->data_mutex);
@@ -857,9 +915,8 @@ err:
  */
 static PyObject *Decoder_has_channel(PyObject *self, PyObject *args)
 {
-       int idx, max_idx;
+       int idx, count;
        struct srd_decoder_inst *di;
-       PyObject *py_channel;
        PyGILState_STATE gstate;
 
        if (!self || !args)
@@ -872,24 +929,20 @@ static PyObject *Decoder_has_channel(PyObject *self, PyObject *args)
                goto err;
        }
 
-       /* Parse the argument of self.has_channel() into 'py_channel'. */
-       if (!PyArg_ParseTuple(args, "O", &py_channel)) {
+       /*
+        * Get the integer argument of self.has_channel(). Check for
+        * the range of supported PD input channel numbers.
+        */
+       if (!PyArg_ParseTuple(args, "i", &idx)) {
                /* Let Python raise this exception. */
                goto err;
        }
 
-       if (!PyLong_Check(py_channel)) {
-               PyErr_SetString(PyExc_Exception, "channel index not a number");
-               goto err;
-       }
-
-       idx = PyLong_AsLong(py_channel);
-       max_idx = g_slist_length(di->decoder->channels)
-               + g_slist_length(di->decoder->opt_channels) - 1;
-
-       if (idx < 0 || idx > max_idx) {
-               srd_err("Invalid channel index %d/%d.", idx, max_idx);
-               PyErr_SetString(PyExc_Exception, "invalid channel");
+       count = g_slist_length(di->decoder->channels) +
+               g_slist_length(di->decoder->opt_channels);
+       if (idx < 0 || idx >= count) {
+               srd_err("Invalid index %d, PD channel count %d.", idx, count);
+               PyErr_SetString(PyExc_IndexError, "invalid channel index");
                goto err;
        }