summaryrefslogtreecommitdiff
path: root/gnuradio-runtime/lib
diff options
context:
space:
mode:
authorJacob Gilbert <mrjacobagilbert@gmail.com>2020-05-02 08:38:05 -0600
committermormj <34754695+mormj@users.noreply.github.com>2020-05-05 13:12:28 -0400
commit941c6c895a5724c142cfb0a32220885062373d57 (patch)
tree2570272007f0cc061a41bd1fed04cb7c7d11fa86 /gnuradio-runtime/lib
parent09b0db2b9852c9e9ab7606622d78d9bf83f584ef (diff)
pmt: stop treating all pairs like they are dicts
create a new derived class for pmt dicts so they can be distinguished without complicated try/catch logic, updated QA with a few additional checks. also added an is_pdu() method which returns true if the pmt is a pair of a dict-type PMT and a uniform-vector type, otherwise false
Diffstat (limited to 'gnuradio-runtime/lib')
-rw-r--r--gnuradio-runtime/lib/pmt/pmt.cc41
-rw-r--r--gnuradio-runtime/lib/pmt/pmt_int.h9
-rw-r--r--gnuradio-runtime/lib/pmt/pmt_serialize.cc20
-rw-r--r--gnuradio-runtime/lib/pmt/qa_pmt_prims.cc22
4 files changed, 76 insertions, 16 deletions
diff --git a/gnuradio-runtime/lib/pmt/pmt.cc b/gnuradio-runtime/lib/pmt/pmt.cc
index 7ea1c9a5b5..a421b55ba9 100644
--- a/gnuradio-runtime/lib/pmt/pmt.cc
+++ b/gnuradio-runtime/lib/pmt/pmt.cc
@@ -82,6 +82,8 @@ static pmt_any* _any(pmt_t x) { return dynamic_cast<pmt_any*>(x.get()); }
// Globals
////////////////////////////////////////////////////////////////////////////
+pmt_null::pmt_null() {}
+
pmt_t get_PMT_NIL()
{
static pmt_t _NIL = pmt_t(new pmt_null());
@@ -314,7 +316,6 @@ std::complex<double> to_complex(pmt_t x)
// Pairs
////////////////////////////////////////////////////////////////////////////
-pmt_null::pmt_null() {}
pmt_pair::pmt_pair(const pmt_t& car, const pmt_t& cdr) : d_car(car), d_cdr(cdr) {}
bool is_null(const pmt_t& x) { return x == PMT_NIL; }
@@ -658,10 +659,23 @@ void* uniform_vector_writable_elements(pmt_t vector, size_t& len)
* Chris Okasaki, 1998, section 3.3.
*/
-bool is_dict(const pmt_t& obj) { return is_null(obj) || is_pair(obj); }
+pmt_dict::pmt_dict(const pmt_t& car, const pmt_t& cdr) : pmt_pair::pmt_pair(car, cdr) {}
+
+bool is_dict(const pmt_t& obj) { return is_null(obj) || obj->is_dict(); }
pmt_t make_dict() { return PMT_NIL; }
+pmt_t dcons(const pmt_t& x, const pmt_t& y)
+{
+ // require arguments to be a PMT pair and PMT dictionary respectively
+ if (!is_pair(x))
+ throw wrong_type("pmt_dcons: not a pair", x);
+ if (!is_dict(y))
+ throw wrong_type("pmt_dcons: not a dict", y);
+
+ return pmt_t(new pmt_dict(x, y));
+}
+
pmt_t dict_add(const pmt_t& dict, const pmt_t& key, const pmt_t& value)
{
if (is_null(dict))
@@ -693,7 +707,7 @@ pmt_t dict_delete(const pmt_t& dict, const pmt_t& key)
if (eqv(caar(dict), key))
return cdr(dict);
- return cons(car(dict), dict_delete(cdr(dict), key));
+ return dcons(car(dict), dict_delete(cdr(dict), key));
}
pmt_t dict_ref(const pmt_t& dict, const pmt_t& key, const pmt_t& not_found)
@@ -814,6 +828,11 @@ size_t blob_length(pmt_t blob)
// General Functions
////////////////////////////////////////////////////////////////////////////
+bool is_pdu(const pmt_t& obj)
+{
+ return is_pair(obj) && is_dict(car(obj)) && is_uniform_vector(cdr(obj));
+}
+
bool eq(const pmt_t& x, const pmt_t& y) { return x == y; }
bool eqv(const pmt_t& x, const pmt_t& y)
@@ -904,6 +923,7 @@ size_t length(const pmt_t& x)
if (x->is_null())
return 0;
+ // also returns correct result for dictionaries
if (x->is_pair()) {
size_t length = 1;
pmt_t it = cdr(x);
@@ -918,8 +938,6 @@ size_t length(const pmt_t& x)
throw wrong_type("pmt_length", x);
}
- // FIXME dictionary length (number of entries)
-
throw wrong_type("pmt_length", x);
}
@@ -986,9 +1004,16 @@ pmt_t reverse(pmt_t listx)
pmt_t list = listx;
pmt_t r = PMT_NIL;
- while (is_pair(list)) {
- r = cons(car(list), r);
- list = cdr(list);
+ if (is_dict(listx)) {
+ while (is_pair(list)) {
+ r = dcons(car(list), r);
+ list = cdr(list);
+ }
+ } else {
+ while (is_pair(list)) {
+ r = cons(car(list), r);
+ list = cdr(list);
+ }
}
if (is_null(list))
return r;
diff --git a/gnuradio-runtime/lib/pmt/pmt_int.h b/gnuradio-runtime/lib/pmt/pmt_int.h
index c7dcb81193..cabd44e8c2 100644
--- a/gnuradio-runtime/lib/pmt/pmt_int.h
+++ b/gnuradio-runtime/lib/pmt/pmt_int.h
@@ -128,6 +128,15 @@ public:
void set_cdr(pmt_t cdr) { d_cdr = cdr; }
};
+class pmt_dict : public pmt_pair
+{
+public:
+ pmt_dict(const pmt_t& car, const pmt_t& cdr);
+ //~pmt_dict(){};
+
+ bool is_dict() const { return true; }
+};
+
class pmt_vector : public pmt_base
{
std::vector<pmt_t> d_v;
diff --git a/gnuradio-runtime/lib/pmt/pmt_serialize.cc b/gnuradio-runtime/lib/pmt/pmt_serialize.cc
index 696ac33695..6bc40b041a 100644
--- a/gnuradio-runtime/lib/pmt/pmt_serialize.cc
+++ b/gnuradio-runtime/lib/pmt/pmt_serialize.cc
@@ -21,7 +21,7 @@
namespace pmt {
-static pmt_t parse_pair(std::streambuf& sb);
+static pmt_t parse_pair(std::streambuf& sb, uint8_t type);
// ----------------------------------------------------------------
// output primitives
@@ -279,7 +279,7 @@ tail_recursion:
}
if (is_pair(obj)) {
- ok = serialize_untagged_u8(PST_PAIR, sb);
+ ok = serialize_untagged_u8(is_dict(obj) ? PST_DICT : PST_PAIR, sb);
ok &= serialize(car(obj), sb);
if (!ok)
return false;
@@ -570,7 +570,10 @@ pmt_t deserialize(std::streambuf& sb)
return from_long(u64);
case PST_PAIR:
- return parse_pair(sb);
+ return parse_pair(sb, PST_PAIR);
+
+ case PST_DICT:
+ return parse_pair(sb, PST_DICT);
case PST_DOUBLE:
if (!deserialize_untagged_f64(&f64, sb))
@@ -694,7 +697,6 @@ pmt_t deserialize(std::streambuf& sb)
}
}
- case PST_DICT:
case PST_COMMENT:
throw notimplemented("pmt::deserialize: tag value = ", from_long(tag));
@@ -730,9 +732,9 @@ pmt_t deserialize_str(std::string s)
* This is a mostly non-recursive implementation that allows us to
* deserialize very long lists w/o exhausting the evaluation stack.
*
- * On entry we've already eaten the PST_PAIR tag.
+ * On entry we've already eaten the PST_PAIR or PST_DICT tag.
*/
-pmt_t parse_pair(std::streambuf& sb)
+pmt_t parse_pair(std::streambuf& sb, uint8_t type)
{
uint8_t tag;
pmt_t val, expr, lastnptr, nptr;
@@ -744,7 +746,11 @@ pmt_t parse_pair(std::streambuf& sb)
while (1) {
expr = deserialize(sb); // read the car
- nptr = cons(expr, PMT_NIL); // build new cell
+ if (type == PST_DICT)
+ nptr = dcons(expr, PMT_NIL); // build new cell
+ else
+ nptr = cons(expr, PMT_NIL); // build new cell
+
if (is_null(lastnptr))
val = nptr;
else
diff --git a/gnuradio-runtime/lib/pmt/qa_pmt_prims.cc b/gnuradio-runtime/lib/pmt/qa_pmt_prims.cc
index 928dab212f..e8338bbd50 100644
--- a/gnuradio-runtime/lib/pmt/qa_pmt_prims.cc
+++ b/gnuradio-runtime/lib/pmt/qa_pmt_prims.cc
@@ -383,7 +383,27 @@ BOOST_AUTO_TEST_CASE(test_dict)
// std::cout << "pmt::dict_keys: " << pmt::dict_keys(dict) << std::endl;
// std::cout << "pmt::dict_values: " << pmt::dict_values(dict) << std::endl;
BOOST_CHECK(pmt::equal(keys, pmt::dict_keys(dict)));
- BOOST_CHECK(pmt::equal(vals, pmt::dict_values(dict)));
+
+ dict = pmt::dict_delete(dict, k1);
+ BOOST_CHECK(pmt::eqv(pmt::dict_ref(dict, k0, not_found), v0));
+ BOOST_CHECK(pmt::is_dict(dict));
+ dict = pmt::dict_add(dict, k3, v3);
+ dict = pmt::reverse(dict);
+ BOOST_CHECK(pmt::eqv(pmt::dict_ref(dict, k0, not_found), v0));
+ BOOST_CHECK(pmt::is_dict(dict));
+}
+
+BOOST_AUTO_TEST_CASE(test_pdu)
+{
+ pmt::pmt_t dict = pmt::dict_add(pmt::make_dict(), pmt::mp("k0"), pmt::mp("v0"));
+ pmt::pmt_t vec = pmt::make_u8vector(1, 0);
+ BOOST_CHECK(!pmt::is_pdu(pmt::PMT_T));
+ BOOST_CHECK(!pmt::is_pdu(vec));
+ BOOST_CHECK(!pmt::is_pdu(dict));
+ BOOST_CHECK(!pmt::is_pdu(pmt::cons(dict, pmt::PMT_NIL)));
+ BOOST_CHECK(!pmt::is_pdu(pmt::cons(pmt::PMT_F, vec)));
+ BOOST_CHECK(pmt::is_pdu(pmt::cons(pmt::make_dict(), vec)));
+ BOOST_CHECK(pmt::is_pdu(pmt::cons(dict, vec)));
}
BOOST_AUTO_TEST_CASE(test_io)