diff options
author | Jacob Gilbert <mrjacobagilbert@gmail.com> | 2020-05-02 08:38:05 -0600 |
---|---|---|
committer | mormj <34754695+mormj@users.noreply.github.com> | 2020-05-05 13:12:28 -0400 |
commit | 941c6c895a5724c142cfb0a32220885062373d57 (patch) | |
tree | 2570272007f0cc061a41bd1fed04cb7c7d11fa86 /gnuradio-runtime/lib | |
parent | 09b0db2b9852c9e9ab7606622d78d9bf83f584ef (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.cc | 41 | ||||
-rw-r--r-- | gnuradio-runtime/lib/pmt/pmt_int.h | 9 | ||||
-rw-r--r-- | gnuradio-runtime/lib/pmt/pmt_serialize.cc | 20 | ||||
-rw-r--r-- | gnuradio-runtime/lib/pmt/qa_pmt_prims.cc | 22 |
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) |