From b72ac6279e0b0cb124c2407b5bf5a0323501e83e Mon Sep 17 00:00:00 2001 From: Emmanuel Nyarko Date: Thu, 22 Feb 2024 21:22:40 +0000 Subject: [PATCH] Early stage bindings for set on CppRuntime_Gcc --- extras/test.cpp | 4 + source/stdcpp/set.d | 207 +++++++++++++++++++++++++++++++++++++++ source/stdcpp/test/set.d | 49 +++++++++ source/stdcpp/utility.d | 8 ++ 4 files changed, 268 insertions(+) create mode 100644 source/stdcpp/set.d create mode 100644 source/stdcpp/test/set.d diff --git a/extras/test.cpp b/extras/test.cpp index f680df7..a02a1d1 100644 --- a/extras/test.cpp +++ b/extras/test.cpp @@ -10,6 +10,7 @@ #include #include #include +#include namespace stdcpp { namespace test { @@ -33,3 +34,6 @@ template std::size_t stdcpp::test::cppSizeOf >(); template class std::vector; template std::size_t stdcpp::test::cppSizeOf >(); + +template class std::set; +template std::size_t stdcpp::test::cppSizeOf >(); diff --git a/source/stdcpp/set.d b/source/stdcpp/set.d new file mode 100644 index 0000000..e33433a --- /dev/null +++ b/source/stdcpp/set.d @@ -0,0 +1,207 @@ +/** + * D header file for interaction with C++ std::set. + * + * Copyright: Copyright (c) 2018 D Language Foundation + * License: Distributed under the + * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0). + * (See accompanying file LICENSE) + * Authors: Emmanuel Nyarko + */ + +module stdcpp.set; + +import stdcpp.allocator; +import stdcpp.utility; +import stdcpp.xutility : StdNamespace; +extern(C++, (StdNamespace)): + +alias set(Key) = set!(Key, less!Key, allocator!(Key)); +extern(C++, class) struct set(Key, compare, Alloc) +{ /// + alias key_type = Key; + /// + alias value_type = Key; + /// + alias size_type = size_t; + /// + alias difference_type = ptrdiff_t; + /// + alias key_compare = compare; + /// + alias value_compare = compare; + /// + alias allocator_type = Alloc; + /// + alias pointer = Key*; + + version (CppRuntime_Gcc) + { + /// + this(const ref allocator!(Key)); + /// + extern(D) this(const compare comp) + { + allocator!(Key) alloc_instance = allocator!(Key).init; + this(comp, alloc_instance); + } + + this(const ref compare comp, ref const allocator!(Key) alloc); + /// + this(ref const set __x) + { + allocator!Key alloc_instance = allocator!Key.init; + this(__x, alloc_instance); + } + /// + this(ref const set!(Key) __x, ref const allocator!(Key)); + /// + allocator_type get_allocator() const nothrow; + /// + size_type size() const nothrow; + /// + bool empty() const nothrow; + /// + size_type max_size() const nothrow; + /// + void clear() nothrow; + + size_type erase(ref const Key key_var); + /// + extern(D) size_type erase(const Key item) + { + return this.erase(item); + } + /// + extern(D) size_type count(const Key item) const + { + return this.count(item); + } + + size_type count(const ref Key key_var) const; + + inout(pointer) find(const ref Key key_var) inout; + /// + extern(D) inout(pointer) find(const Key item) inout + { + return this.find(item); + } + + pair!(pointer, bool) insert (ref const Key val); + /// + extern(D) pair!(pointer, bool) insert ( const Key val) + { + return this.insert(val); + } + /// + void swap(ref set other) nothrow; + /// + void merge(C2)( ref set!(Key, C2, allocator!(Key)) source ); + + bool contains(ref const Key key_var) const + { + return Rep_type.find(key_var) != Rep_type.end(); + } + /// + extern(D) bool contains(const Key item) const + { + return this.contains(item); + } + + pair!(pointer, pointer) equal_range(ref const Key key_var); + /// + extern(D) pair!(pointer, pointer) equal_range(const Key item) + { + return equal_range(item); + } + + inout(pointer) lower_bound(ref const Key key_var) inout; + /// + extern(D) inout(pointer) lower_bound( const Key item) inout + { + return lower_bound(item); + } + + inout(pointer) lower_bound(K)(ref const K x) inout; + /// + extern(D) inout(pointer) lower_bound(Y)(const Y z) inout + { + return lower_bound!(Y)(z); + } + + inout(pointer) upper_bound(K)(ref const K x) inout; + /// + extern(D) inout(pointer) upper_bound(Y)(const Y z) inout + { + return upper_bound!(Y)(z); + } + + inout(pointer) upper_bound(K)(ref const K x) inout; + /// + extern(D) inout(pointer) upper_bound(Y)(const Y z) inout + { + return upper_bound!(Y)(z); + } + + ///observers + key_compare key_comp() const; + /// + value_compare value_comp() const; + + _Rb_tree!(key_type, value_type, _Identity!(value_type), key_compare, Alloc) Rep_type; + } + else version (CppRuntime_Microsoft) + { + static assert(0, "CppRuntime not yet supported"); + } +} + +private: +version (CppRuntime_Gcc) +{ + extern(C++) struct _Identity(T) + { + + } + enum _Rb_tree_color { red = false, black = true}; + struct _Rb_tree_node_base + { + _Rb_tree_color _M_color; + _Rb_tree_node_base* parent; + _Rb_tree_node_base* left; + _Rb_tree_node_base* right; + } + + struct _Rb_tree_node(Val) + { + _Rb_tree_node_base _base; + Val _M_value_field; + } + + struct _Rb_tree_key_compare(U) + { + U _M_key_compare; + } + + struct _Rb_tree_header + { + _Rb_tree_node_base _M_header; + size_t _M_node_count; + } + + extern(C++, class) struct _Rb_tree(_Key, _Val, _KeyOfValue, Compare, _Alloc) + { + alias pointer = _Key*; + + struct _Rb_tree_impl(_Key_compare) + { + _Rb_tree_header b; + _Rb_tree_key_compare!(_Key_compare) a; + } + + _Rb_tree_impl!Compare _M_impl; + + inout(pointer) end() inout nothrow; + + inout(pointer) find(const ref _Key __k) inout; + } +} diff --git a/source/stdcpp/test/set.d b/source/stdcpp/test/set.d new file mode 100644 index 0000000..6208b03 --- /dev/null +++ b/source/stdcpp/test/set.d @@ -0,0 +1,49 @@ +/******************************************************************************* + + Tests for `std::set` + +*******************************************************************************/ + +module stdcpp.test.set; + +import stdcpp.set; +import stdcpp.test.base; +import stdcpp.utility : less; +version (CppRuntime_Gcc) +{ + unittest + { + assert(cppSizeOf!(set!int) == set!int.sizeof); + } + + unittest + { + import stdcpp.allocator; + allocator!int alloc_instance = allocator!(int).init; + less!int a; + auto p = set!int(a); + p.insert(5); + assert(p.size == 1); + assert(p.empty == 0); + p.erase(5); + p.insert(6); + p.clear; + assert(p.size == 0); + assert(p.empty == 1); + set!int q = a; + q.swap(p); + q.insert(4); + q.insert(4); + q.insert(4); + assert(q.size == 1); + assert(q.count(4) == 1);//count for set only results in 0 for not present or 1 for present + assert(q.count(5) == 0); + assert(q.contains(4) == 1); // q contains 4 evaluates to true + auto iter = q.find(4); + set!int w = q; //copy constructor + assert(w.size() == 1); + auto alloc = set!int(alloc_instance); + alloc.insert(5); + assert(alloc.size() == 1); + } +} \ No newline at end of file diff --git a/source/stdcpp/utility.d b/source/stdcpp/utility.d index 45099ea..58aeeb4 100644 --- a/source/stdcpp/utility.d +++ b/source/stdcpp/utility.d @@ -48,3 +48,11 @@ struct pair(T1, T2) } } } + +struct less(T) +{ + static bool opCall(const ref T left, const ref T right) + { + return left < right; + } +}