Skip to content

Commit

Permalink
Add rudimentary bindings to std::unordered_map
Browse files Browse the repository at this point in the history
It's used heavily in the quorum intersection
checker code which will be binded to soon.
  • Loading branch information
AndrejMitrovic committed Mar 17, 2020
1 parent dbd8a5c commit 6524b2c
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 0 deletions.
56 changes: 56 additions & 0 deletions source/scpd/Cpp.d
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,20 @@ extern(C++) private int cpp_set_foreach(T)(void* set, void* ctx, void* cb);
/// std::set.empty() support
nothrow pure @nogc extern(C++) private bool cpp_set_empty(T)(const(void)* set);

/// unordered map assignment support
private nothrow @nogc extern(C++) void cpp_unordered_map_assign (K, V)(
void* map, const(void)* key, const(void)* value);

/// unordered map length support
private pure nothrow @nogc @safe extern(C++) size_t cpp_unordered_map_length (K, V)(
const(void)* map);

// @bug with substitution
//private pure nothrow @nogc @safe extern(C++) unordered_map!(K, V)* cpp_unordered_map_create (K, V)();

/// Create a new unordered map with the given Key/T types, and return a pointer to it
private pure nothrow @nogc @safe extern(C++) void* cpp_unordered_map_create (K, V)();

extern(C++, `std`) {
/// Binding: Needs to be instantiated on C++ side
shared_ptr!T make_shared(T, Args...)(Args args);
Expand Down Expand Up @@ -121,6 +135,38 @@ extern(C++, `std`) {
void*[3] ptr;
}

/// Rudimentary bindings for std::unordered_map
public struct unordered_map (Key, T, Hash = hash!Key, KeyEqual = equal_to!Key, Allocator = allocator!(pair!(const Key, T)))
{
private void* ptr;

extern(D) void opIndexAssign (in T value, in Key key) @trusted @nogc nothrow
{
cpp_unordered_map_assign!(Key, T)(
this.ptr, cast(void*)&key, cast(void*)&value);
}

extern(D) size_t length () pure nothrow @safe @nogc
{
return cpp_unordered_map_length!(Key, T)(this.ptr);
}

/// create a new unordered map allocated on the C++ side.
/// Note that we currently only use this in unittests
extern(D) static unordered_map create () pure @trusted @nogc nothrow
{
return unordered_map(cpp_unordered_map_create!(Key, T)());
}
}

unittest
{
auto map = unordered_map!(int, int).create();
assert(map.length() == 0);
map[1] = 1;
assert(map.length() == 1);
}

// only used at compile-time on the C++ side, here for mangling
struct ratio (int _Num, int _Den = 1)
{
Expand Down Expand Up @@ -170,8 +216,18 @@ unittest
/// Can't import `core.stdcpp.allocator` because it transitively imports
/// `core.stdcpp.exception`
/// In this case we just need to get the name right for `vector`

extern(C++, (StdNS!())) struct allocator (T) {}

// fake std::pair
private extern(C++, (StdNS!())) struct pair (T1, T2) {}

// fake std::hash
private extern(C++, (StdNS!())) struct hash (T) {}

// fake std::equal_to
private extern(C++, (StdNS!())) struct equal_to (T = void) {}

/*******************************************************************************
Simple bindings from `std::vector`
Expand Down
14 changes: 14 additions & 0 deletions source/scpp/extra/DUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,20 @@ CPPSETEMPTYINST(SCPBallot)
CPPSETEMPTYINST(PublicKey)
CPPSETEMPTYINST(unsigned int)

#define CPPUNORDEREDMAPASSIGNINST(K, V) template void cpp_unordered_map_assign<K, V>(void*, const void*, const void*);
CPPUNORDEREDMAPASSIGNINST(NodeID, std::shared_ptr<SCPQuorumSet>)
CPPUNORDEREDMAPASSIGNINST(int, int)

#define CPPUNORDEREDMAPLENGTHINST(K, V) template std::size_t cpp_unordered_map_length<K, V>(const void*);
CPPUNORDEREDMAPLENGTHINST(NodeID, std::shared_ptr<SCPQuorumSet>)
CPPUNORDEREDMAPLENGTHINST(int, int)

// @bug with substitution
// #define CPPUNORDEREDMAPCREATEINST(K, V) template std::unordered_map<K, V>* cpp_unordered_map_create<K, V>();
#define CPPUNORDEREDMAPCREATEINST(K, V) template void* cpp_unordered_map_create<K, V>();
CPPUNORDEREDMAPCREATEINST(NodeID, std::shared_ptr<SCPQuorumSet>)
CPPUNORDEREDMAPCREATEINST(int, int)

void callCPPDelegate (void* cb)
{
auto callback = (std::function<void()>*)cb;
Expand Down
32 changes: 32 additions & 0 deletions source/scpp/extra/DUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
// Not originally part of SCP but required for the D side to work

#include <set>
#include <unordered_map>
#include <vector>

#include "crypto/SecretKey.h" // for operator() (hashing support)

// rudimentary support for walking through an std::set
// note: can't use proper callback type due to
// https://issues.dlang.org/show_bug.cgi?id=20223
Expand All @@ -30,6 +33,35 @@ bool cpp_set_empty(const void* setptr)
return ((const std::set<T>*)setptr)->empty();
}

template<typename K, typename V>
void cpp_unordered_map_assign (void* map, const void* key, const void* value)
{
auto k = (K*)key;
auto v = (V*)value;
auto m = (std::unordered_map<K, V>*)map;
(*m)[*k] = *v;
}

template<typename K, typename V>
std::size_t cpp_unordered_map_length (const void* map)
{
auto m = (std::unordered_map<K, V>*)map;
return m->size();
}

template<typename K, typename V>
void* cpp_unordered_map_create ()
{
return new std::unordered_map<K, V>();
}

// @bug with substitution
// template<typename K, typename V>
// std::unordered_map<K, V> * cpp_unordered_map_create ()
// {
// return new std::unordered_map<K, V>();
// }

template<typename T, typename VectorT>
void push_back(VectorT& this_, T& value)
{
Expand Down

0 comments on commit 6524b2c

Please sign in to comment.