Skip to content

Commit

Permalink
map, wip
Browse files Browse the repository at this point in the history
Signed-off-by: Josh Morman <[email protected]>
  • Loading branch information
mormj committed Oct 25, 2022
1 parent 3f0f69d commit e8cbf95
Show file tree
Hide file tree
Showing 5 changed files with 260 additions and 2 deletions.
10 changes: 9 additions & 1 deletion include/pmtv/base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ class pmt {

_pmt_storage storage() const noexcept { return _value; }

operator _pmt_storage() const {
return storage();
}


protected:
_pmt_storage _value;
};
Expand All @@ -122,7 +127,8 @@ pmt::pmt(const T& other) {
// Vector of uniform arithmetic types
_value = std::make_shared<std::vector<typename T::value_type>>(other.begin(), other.end());
}
else if constexpr(associative_array<T>) {
//else if constexpr(associative_array<T>) {
else if constexpr(PmtMap<T>) {
// Map or hash table
_value = std::make_shared<std::map<std::string, _pmt_storage>>(other.begin(), other.end());
}
Expand Down Expand Up @@ -508,6 +514,8 @@ std::ostream& operator<<(std::ostream& os, const P& value) {
, value.storage().base());
}



// Explicit cast std::vector


Expand Down
141 changes: 141 additions & 0 deletions include/pmtv/map.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#pragma once

#include <map>
#include <pmtv/base.hpp>
#include <ranges>
#include <span>

namespace pmtv {

/**
* @brief map of keys of type string to pmts
*
*/
class map : public pmt {
public:
using key_type = std::string;
using mapped_type = _pmt_storage;
using value_type = std::pair<const key_type, mapped_type>;
using reference = value_type &;
using const_reference = const value_type &;
using map_type = std::map<key_type, mapped_type>;
using size_type = size_t;
using map_sptr = std::shared_ptr<map_type>;

using iterator = map_type::iterator;
using const_iterator = map_type::const_iterator;
// Construct empty map
map() : pmt(map_type{}) {}
// Copy from std map
map(const map_type &other) : pmt(other) {}

// Copy from std map
map(const std::map<std::string, pmt> &other) : pmt(map_type{}) {
for (auto &[k, v] : other) {
// FIXME - the [] operator seems to be returning
// the variant by value, not by reference
this->operator[](k) = v.storage();
// auto x = this->operator[](k);
// x = v.storage();
}
}

// // Copy from pmt
// template <class T, typename = IsPmt<T>>
// map(const T& other) {
// if (other.data_type() != data_type())
// throw ConversionError(other, "map");
// _map = other;
// }
// map(std::initializer_list<value_type> il) {
// _MakeEmptyMap();
// for (auto& [k, v]: il)
// this->operator[](k) = v;
// }
// //template <class T>
// //map(std::map<string
// ~map() {}

/**************************************************************************
* Iterators
**************************************************************************/
typename map_type::iterator begin() noexcept { return _get_map()->begin(); }
typename map_type::const_iterator begin() const noexcept {
return _get_map()->begin();
}
typename map_type::iterator end() noexcept { return _get_map()->end(); }
typename map_type::const_iterator end() const noexcept {
return _get_map()->end();
}

/**************************************************************************
* Element Access
**************************************************************************/
mapped_type &at(const key_type &key) { return _get_map()->at(key); }
const mapped_type &at(const key_type &key) const {
return _get_map()->at(key);
}
mapped_type &operator[](const key_type &key) {
return _get_map()->operator[](key);
}

// size_t size() const { return _get_map()->size(); }
// size_t count(const key_type& key) const { return
// _get_map()->count(key); }

// static constexpr Data data_type() { return
// DataTraits<type>::enum_value; } const pmt& get_pmt_buffer() const {
// return _map; }

// //! Equality Comparisons
// // Declared as class members so that we don't do implicit
// conversions. template <class U> bool operator==(const U& x) const;
// template <class U>
// bool operator!=(const U& x) const { return !(operator==(x));}
// void pre_serial_update() const {
// // It may look odd to declare this function as const when it
// modifies
// // count. But count is part of the internal interface, so to the
// // user, this is a const function.
// std::shared_ptr<base_buffer> scalar = _map._scalar;
// scalar->data_as<type>()->mutate_count(_get_map()->size());
// }

private:
map_sptr _get_map() { return std::get<map_sptr>(_value); }
const map_sptr _get_map() const { return std::get<map_sptr>(_value); }
};

// template <class T, class U>
// using IsNotVectorT = std::enable_if_t<!std::is_same_v<uniform_vector<T>, U>,
// bool>;

// // Reversed case. This allows for x == y and y == x
// template <class T, class U, typename = IsNotVectorT<T, U> >
// bool operator==(const U& y, const uniform_vector<T>& x) {
// return x.operator==(y);
// }

// template<>
// bool PmtEqual(const std::vector<T>& arg, const uniform_vector<T>& other) {

// }

template <class T> using IsMap = std::enable_if_t<std::is_same_v<map, T>, bool>;

// Need to have map operator here because it has pmts in it.
template <class T, IsMap<T> = true>
std::ostream &operator<<(std::ostream &os, const T &value) {
os << "{ ";
bool first = true;
for (const auto &[k, v] : value) {
if (!first)
os << ", ";
first = false;
os << k << ": " << pmt(v);
}
os << " }";
return os;
}

} // namespace pmtv
3 changes: 3 additions & 0 deletions include/pmtv/type_helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ concept UniformVectorInsidePmt = IsSharedPtr<T> && UniformVector<typename T::ele
template <typename T>
concept PmtMap = std::is_same_v<T, std::map<std::string, _pmt_storage>>;

template <typename T>
concept PmtMapInsidePmt = IsSharedPtr<T> && PmtMap<T>;

template <typename T>
concept PmtVector = std::is_same_v<T, std::vector<_pmt_storage>>;

Expand Down
3 changes: 2 additions & 1 deletion test/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ TEST_ENV.prepend('PYTHONPATH', join_paths(meson.project_build_root(),'python') )
# GR namespace tests
qa_srcs = ['qa_scalar',
'qa_uniform_vector',
'qa_vector_of_pmts'
'qa_vector_of_pmts',
'qa_map'
]
deps = [pmt_dep,
gtest_dep]
Expand Down
105 changes: 105 additions & 0 deletions test/qa_map.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*-*-c++-*-*/
/*
* Copyright 2021 John Sallay
*
* SPDX-License-Identifier: LGPL-3.0
*
*/
#include <gtest/gtest.h>
#include <complex>

#include <pmtv/map.hpp>
#include <pmtv/uniform_vector.hpp>

using namespace pmtv;

TEST(PmtMap, EmptyMap) {
map empty;
empty["abc"] = pmt(uint64_t(4));
empty["xyz"] = pmt(std::vector<double>{1,2,3,4,5});
}


TEST(PmtMap, PmtMapTests)
{
std::complex<float> val1(1.2, -3.4);
std::vector<int32_t> val2{ 44, 34563, -255729, 4402 };

// Create the PMT map
std::map<std::string, pmt> input_map({
{ "key1", val1 },
{ "key2", val2 },
});
map map_pmt(input_map);
std::cout << map_pmt << std::endl;
std::cout << pmt(val1) << std::endl;

// Lookup values in the PMT map and compare with what was put in there
pmt vv1 = map_pmt["key1"];
std::cout << std::complex<float>(vv1) << std::endl;
std::cout << "Before" << std::endl;
std::cout << vv1 << std::endl;
EXPECT_TRUE(std::complex<float>(vv1) == val1);

auto vv2 = map_pmt["key2"];
EXPECT_TRUE(uniform_vector<int32_t>(vv2) == val2);
std::cout << map_pmt << std::endl;
}
#if 0
TEST(PmtMap, MapSerialize)
{
std::complex<float> val1(1.2, -3.4);
std::vector<int32_t> val2{ 44, 34563, -255729, 4402 };

// Create the PMT map
std::map<std::string, pmt> input_map({
{ "key1", val1 },
{ "key2", val2 },
});
map map_pmt(input_map);
std::stringbuf sb;
map_pmt.get_pmt_buffer().serialize(sb);
auto y = pmt::deserialize(sb);
EXPECT_EQ(map_pmt, y);

}

TEST(PmtMap, get_as)
{
std::complex<float> val1(1.2, -3.4);
std::vector<int32_t> val2{ 44, 34563, -255729, 4402 };

// Create the PMT map
std::map<std::string, pmt> input_map({
{ "key1", val1 },
{ "key2", val2 },
});
pmt x = input_map;
// Make sure that we can get the value back out
auto y = get_as<std::map<std::string, pmt>>(x);
EXPECT_EQ(x, y);

// Throw an error for other types.
EXPECT_THROW(get_as<float>(x), ConversionError);

}

TEST(PmtMap, base64)
{
std::complex<float> val1(1.2, -3.4);
std::vector<int32_t> val2{ 44, 34563, -255729, 4402 };

// Create the PMT map
std::map<std::string, pmt> input_map({
{ "key1", val1 },
{ "key2", val2 },
});
pmt x = input_map;

// Make sure that we can get the value back out
auto encoded_str = pmt(x).to_base64();
auto y = pmt::from_base64(encoded_str);

EXPECT_EQ(x, y);
}
#endif

0 comments on commit e8cbf95

Please sign in to comment.