]> sigrok.org Git - libsigrok.git/commitdiff
bindings: add u32/SR_T_UINT32 support for config keys
authorMarkus Heidelberg <redacted>
Sun, 11 Dec 2022 00:28:55 +0000 (01:28 +0100)
committerGerhard Sittig <redacted>
Mon, 19 Dec 2022 08:11:36 +0000 (09:11 +0100)
Previous bindings for C++ and other languages lacked support for the
uint32_t data type for config keys. Which terminated the program with
the message:

  Exception: internal error

The following PulseView commands reproduced the issue:

  $ pulseview -i /dev/null -I csv:single_column=1
  $ pulseview -i /dev/null -I csv:first_column=1
  $ pulseview -i /dev/null -I csv:logic_channels=1
  $ pulseview -i /dev/null -I csv:start_line=1

  $ pulseview -i /dev/null -I saleae:wordsize=1
  $ pulseview -i /dev/null -I saleae:logic_channels=1

  $ pulseview -i /dev/null -I vcd:numchannels=1

Add support for uint32_t data types in the C++, Python, and Ruby
language bindings.

[ gsi: separate stou32() helper ]

bindings/cxx/ConfigKey_methods.cpp
bindings/cxx/classes.cpp
bindings/python/sigrok/core/classes.i
bindings/ruby/classes.i
include/libsigrok/libsigrok.h
src/hwdriver.c

index 7381c922f3203e58a97e83d6d5a48bab3e4beae1..d899ddcc2a18d2053470a346051e6f4e5ccca27f 100644 (file)
@@ -100,6 +100,20 @@ static inline unsigned long stoul(const std::string &str)
 }
 #endif
 
+// Conversion from text to uint32_t, including a range check.
+// This is sigrok specific, _not_ part of any C++ standard library.
+static uint32_t stou32(const std::string &str)
+{
+       unsigned long ret;
+       errno = 0;
+       ret = stoul(str);
+       if (errno == ERANGE)
+               throw std::out_of_range("stou32");
+       if (ret > std::numeric_limits<uint32_t>::max())
+               throw std::out_of_range("stou32");
+       return ret;
+}
+
 Glib::VariantBase ConfigKey::parse_string(std::string value, enum sr_datatype dt)
 {
        GVariant *variant;
@@ -139,6 +153,13 @@ Glib::VariantBase ConfigKey::parse_string(std::string value, enum sr_datatype dt
                                throw Error(SR_ERR_ARG);
                        }
                        break;
+               case SR_T_UINT32:
+                       try {
+                               variant = g_variant_new_uint32(stou32(value));
+                       } catch (invalid_argument&) {
+                               throw Error(SR_ERR_ARG);
+                       }
+                       break;
                default:
                        throw Error(SR_ERR_BUG);
        }
index de600d039b7b41f2dac6190984e6f6523ccd724b..d5477847653f85acb6f637b48de4a3ce677a9659 100644 (file)
@@ -1565,6 +1565,8 @@ Glib::VariantBase Option::parse_string(string value)
                dt = SR_T_FLOAT;
        } else if (g_variant_is_of_type(tmpl, G_VARIANT_TYPE_INT32)) {
                dt = SR_T_INT32;
+       } else if (g_variant_is_of_type(tmpl, G_VARIANT_TYPE_UINT32)) {
+               dt = SR_T_UINT32;
        } else {
                throw Error(SR_ERR_BUG);
        }
index eb557d0375335f561eb1e05d91f3536c38620c2f..8bccae1d5271aa98ebadf15baab4f07bcb3fa55d 100644 (file)
@@ -340,6 +340,8 @@ Glib::VariantBase python_to_variant_by_key(PyObject *input, const sigrok::Config
         return Glib::Variant<double>::create(PyFloat_AsDouble(input));
     else if (type == SR_T_INT32 && PyInt_Check(input))
         return Glib::Variant<gint32>::create(PyInt_AsLong(input));
+    else if (type == SR_T_UINT32 && PyInt_Check(input))
+        return Glib::Variant<guint32>::create(PyInt_AsLong(input));
     else if ((type == SR_T_RATIONAL_VOLT) && PyTuple_Check(input) && (PyTuple_Size(input) == 2)) {
         PyObject *numObj = PyTuple_GetItem(input, 0);
         PyObject *denomObj = PyTuple_GetItem(input, 1);
@@ -369,6 +371,8 @@ Glib::VariantBase python_to_variant_by_option(PyObject *input,
         return Glib::Variant<double>::create(PyFloat_AsDouble(input));
     else if (type == G_VARIANT_TYPE_INT32 && PyInt_Check(input))
         return Glib::Variant<gint32>::create(PyInt_AsLong(input));
+    else if (type == G_VARIANT_TYPE_UINT32 && PyInt_Check(input))
+        return Glib::Variant<guint32>::create(PyInt_AsLong(input));
     else
         throw sigrok::Error(SR_ERR_ARG);
 }
index 13496a86bb98fc64fc181300aaf2031b19e2ef76..fbd7c36c95d9c57d008c3d128eb11be622269ac4 100644 (file)
@@ -236,6 +236,8 @@ Glib::VariantBase ruby_to_variant_by_key(VALUE input, const sigrok::ConfigKey *k
         return Glib::Variant<double>::create(RFLOAT_VALUE(input));
     else if (type == SR_T_INT32 && RB_TYPE_P(input, T_FIXNUM))
         return Glib::Variant<gint32>::create(NUM2INT(input));
+    else if (type == SR_T_UINT32 && RB_TYPE_P(input, T_FIXNUM))
+        return Glib::Variant<guint32>::create(NUM2UINT(input));
     else
         throw sigrok::Error(SR_ERR_ARG);
 }
@@ -261,6 +263,8 @@ Glib::VariantBase ruby_to_variant_by_option(VALUE input, std::shared_ptr<sigrok:
         return Glib::Variant<double>::create(RFLOAT_VALUE(input));
     else if (variant.is_of_type(Glib::VARIANT_TYPE_INT32) && RB_TYPE_P(input, T_FIXNUM))
         return Glib::Variant<gint32>::create(NUM2INT(input));
+    else if (variant.is_of_type(Glib::VARIANT_TYPE_UINT32) && RB_TYPE_P(input, T_FIXNUM))
+        return Glib::Variant<guint32>::create(NUM2UINT(input));
     else
         throw sigrok::Error(SR_ERR_ARG);
 }
index 42614fd0c79bcf7ff30b7554e022b87b4cbe5370..5300fbe1951e5027a9e587c38b52e1df19590edb 100644 (file)
@@ -153,6 +153,7 @@ enum sr_datatype {
        SR_T_DOUBLE_RANGE,
        SR_T_INT32,
        SR_T_MQ,
+       SR_T_UINT32,
 
        /* Update sr_variant_type_get() (hwdriver.c) upon changes! */
 };
index 572748aceaabd3e3bd699a3802e059d4ad8f298f..7b497e078608ce9e2ee1e9d422152dadd6fd7779 100644 (file)
@@ -331,6 +331,8 @@ SR_PRIV const GVariantType *sr_variant_type_get(int datatype)
        switch (datatype) {
        case SR_T_INT32:
                return G_VARIANT_TYPE_INT32;
+       case SR_T_UINT32:
+               return G_VARIANT_TYPE_UINT32;
        case SR_T_UINT64:
                return G_VARIANT_TYPE_UINT64;
        case SR_T_STRING: