Browse Source

feat(libstdc++): add deduction guides and iter tools

greatbridf 1 year ago
parent
commit
c98321cc3d

+ 34 - 0
gblibstdc++/include/bits/iter_ops

@@ -0,0 +1,34 @@
+#ifndef __GBLIBCPP_BITS_ITER_OPS__
+#define __GBLIBCPP_BITS_ITER_OPS__
+
+namespace std {
+
+template <typename Container>
+constexpr auto begin(Container& c) -> decltype(c.begin())
+{ return c.begin(); }
+
+template <typename Container>
+constexpr auto begin(const Container& c) -> decltype(c.begin())
+{ return c.begin(); }
+
+template <typename Container>
+constexpr auto end(Container& c) -> decltype(c.end())
+{ return c.end(); }
+
+template <typename Container>
+constexpr auto end(const Container& c) -> decltype(c.end())
+{ return c.end(); }
+
+template <typename Container>
+constexpr auto cbegin(const Container& c)
+    noexcept(noexcept(std::begin(c))) -> decltype(c.begin())
+{ return c.begin(); }
+
+template <typename Container>
+constexpr auto cend(const Container& c)
+    noexcept(noexcept(std::end(c))) -> decltype(c.end())
+{ return c.end(); }
+
+} // namespace std
+
+#endif

+ 49 - 5
gblibstdc++/include/list

@@ -1,7 +1,10 @@
 #ifndef __GBLIBCPP_LIST__
 #define __GBLIBCPP_LIST__
 
+#include <bits/iter_ops>
+
 #include <memory>
+#include <initializer_list>
 #include <type_traits>
 #include <utility>
 #include <cstddef>
@@ -224,6 +227,15 @@ public:
 
         _move_from(std::move(other));
     }
+
+    __GBLIBCPP_CONSTEXPR
+    list(std::initializer_list<T> ilist,
+        const Allocator& alloc = Allocator())
+        : list(alloc)
+    {
+        for (const auto& item : ilist)
+            emplace_back(item);
+    }
     
     __GBLIBCPP_CONSTEXPR
     ~list()
@@ -276,11 +288,43 @@ public:
         return *this;
     }
 
-    // TODO: std::initializer_list
-    // list(std::initializer_list<Key> init,
-    //     const Allocator& alloc = Allocator());
-    //
-    // list& operator=(std::initializer_list<Key> ilist);
+    __GBLIBCPP_CONSTEXPR
+    list& operator=(std::initializer_list<T> ilist)
+    {
+        // TODO: reuse memory
+        clear();
+        for (const auto& item : ilist)
+            emplace_back(item);
+        return *this;
+    }
+
+    __GBLIBCPP_CONSTEXPR
+    void assign(size_type count, const T& value)
+    {
+        clear();
+        while (count--)
+            emplace_back(value);
+    }
+
+    template <typename InputIter>
+    __GBLIBCPP_CONSTEXPR
+    void assign(InputIter first, InputIter last)
+    {
+        clear();
+        insert(first, last);
+    }
+
+    __GBLIBCPP_CONSTEXPR
+    void assign(std::initializer_list<T> ilist)
+    {
+        clear();
+        for (const auto& item : ilist)
+            emplace_back(item);
+    }
+
+    __GBLIBCPP_CONSTEXPR
+    allocator_type get_allocator() const noexcept { return m_alloc; }
+
     __GBLIBCPP_CONSTEXPR
     reference front() { return *begin(); }
     __GBLIBCPP_CONSTEXPR

+ 50 - 11
gblibstdc++/include/map

@@ -1,9 +1,12 @@
 #ifndef __GBLIBCPP_MAP__
 #define __GBLIBCPP_MAP__
 
+#include <bits/iter_ops>
+
 #include <bits/rbtree>
 #include <functional>
 #include <memory>
+#include <initializer_list>
 #include <tuple>
 #include <type_traits>
 #include <utility>
@@ -109,6 +112,18 @@ public:
     map(map&& other, const Allocator& alloc)
         : tree(std::move(other.tree), alloc) {}
     
+    __GBLIBCPP_CONSTEXPR
+    map(std::initializer_list<value_type> init,
+        const Compare& comp = Compare(),
+        const Allocator& alloc = Allocator())
+        : map(comp, alloc)
+    { insert(init.begin(), init.end()); }
+
+    __GBLIBCPP_CONSTEXPR
+    map(std::initializer_list<value_type> init,
+        const Allocator& alloc)
+        : map(init, Compare(), alloc) {}
+    
     __GBLIBCPP_CONSTEXPR
     ~map() { clear(); }
     
@@ -116,17 +131,13 @@ public:
     map& operator=(const map& other) = default;
     __GBLIBCPP_CONSTEXPR
     map& operator=(map&& other) = default;
-
-    // TODO: std::initializer_list
-    // set(std::initializer_list<Key> init,
-    //     const Compare& comp = Compare(),
-    //     const Allocator& alloc = Allocator());
-    //
-    // set(std::initializer_list<Key> init,
-    //     const Allocator& alloc = Allocator())
-    //     : set(init, Compare(), alloc) {}
-    //
-    // set& operator=(std::initializer_list<Key> ilist);
+    __GBLIBCPP_CONSTEXPR
+    map& operator=(std::initializer_list<value_type> ilist)
+    {
+        clear();
+        insert(ilist.begin(), ilist.end());
+        return *this;
+    }
 
     __GBLIBCPP_CONSTEXPR
     iterator find(const Key& key) { return tree.find(key); }
@@ -266,6 +277,34 @@ void swap(std::map<Key, T, Compare, Allocator>& lhs,
     std::map<Key, T, Compare, Allocator>& rhs)
 { lhs.swap(rhs); }
 
+template <typename Key, typename T,
+    typename Compare, typename Allocator, typename Pred>
+typename std::map<Key, T, Compare, Allocator>::size_type
+erase_if(std::map<Key, T, Compare, Allocator>& c, Pred pred)
+{
+    auto iter = c.begin();
+    typename std::map<Key, T, Compare, Allocator>::size_type count = 0;
+    while (iter != c.end()) {
+        if (pred(*iter)) {
+            iter = c.erase(iter);
+            ++count;
+        } else
+            ++iter;
+    }
+    return count;
+}
+
+template <typename Key, typename T,
+    typename Compare = std::less<Key>,
+    typename Allocator = std::allocator<std::pair<const Key, T>>>
+map(std::initializer_list<std::pair<Key, T>>,
+    Compare = Compare(), Allocator = Allocator())
+    -> map<Key, T, Compare, Allocator>;
+
+template <typename Key, typename T, typename Allocator>
+map(std::initializer_list<std::pair<Key, T>>, Allocator)
+    -> map<Key, T, std::less<Key>, Allocator>;
+
 } // namespace std
 
 #endif

+ 50 - 11
gblibstdc++/include/set

@@ -1,8 +1,11 @@
 #ifndef __GBLIBCPP_SET__
 #define __GBLIBCPP_SET__
 
+#include <bits/iter_ops>
+
 #include <bits/rbtree>
 #include <functional>
+#include <initializer_list>
 #include <memory>
 #include <cstddef>
 
@@ -81,6 +84,18 @@ public:
     __GBLIBCPP_CONSTEXPR
     set(set&& other, const Allocator& alloc)
         : tree(std::move(other.tree), alloc) {}
+
+    __GBLIBCPP_CONSTEXPR
+    set(std::initializer_list<Key> ilist,
+        const Compare& comp = Compare(),
+        const Allocator& alloc = Allocator())
+        : set(comp, alloc)
+    { insert(ilist.begin(), ilist.end()); }
+    
+    __GBLIBCPP_CONSTEXPR
+    set(std::initializer_list<Key> ilist,
+        const Allocator& alloc)
+        : set(ilist, Compare(), alloc) {}
     
     __GBLIBCPP_CONSTEXPR
     ~set() { clear(); }
@@ -89,17 +104,13 @@ public:
     set& operator=(const set& other) = default;
     __GBLIBCPP_CONSTEXPR
     set& operator=(set&& other) = default;
-
-    // TODO: std::initializer_list
-    // set(std::initializer_list<Key> init,
-    //     const Compare& comp = Compare(),
-    //     const Allocator& alloc = Allocator());
-    //
-    // set(std::initializer_list<Key> init,
-    //     const Allocator& alloc = Allocator())
-    //     : set(init, Compare(), alloc) {}
-    //
-    // set& operator=(std::initializer_list<Key> ilist);
+    __GBLIBCPP_CONSTEXPR
+    set& operator=(std::initializer_list<Key> ilist)
+    {
+        clear();
+        insert(ilist.begin(), ilist.end());
+        return *this;
+    }
 
     __GBLIBCPP_CONSTEXPR
     iterator find(const Key& key) { return tree.find(key); }
@@ -187,6 +198,34 @@ void swap(std::set<Key, Compare, Allocator>& lhs,
     std::set<Key, Compare, Allocator>& rhs)
 { lhs.swap(rhs); }
 
+template <typename Key, typename Compare,
+    typename Allocator, typename Pred>
+typename std::set<Key, Compare, Allocator>::size_type
+erase_if(std::set<Key, Compare, Allocator>& set, Pred pred)
+{
+    auto iter = set.begin();
+    typename std::set<Key, Compare, Allocator>::size_type count = 0;
+    while (iter != set.end()) {
+        if (pred(*iter)) {
+            iter = set.erase(iter);
+            ++count;
+        } else {
+            ++iter;
+        }
+    }
+    return count;
+}
+
+template <typename Key,
+    typename Compare = std::less<Key>,
+    typename Allocator = std::allocator<Key>>
+set(std::initializer_list<Key>, Compare = Compare(),
+    Allocator = Allocator()) -> set<Key, Compare, Allocator>;
+
+template <typename Key, typename Allocator>
+set(std::initializer_list<Key>, Allocator)
+    -> set<Key, std::less<Key>, Allocator>;
+
 } // namespace std
 
 #endif

+ 2 - 0
gblibstdc++/include/vector

@@ -1,6 +1,8 @@
 #ifndef __GBLIBCPP_VECTOR__
 #define __GBLIBCPP_VECTOR__
 
+#include <bits/iter_ops>
+
 #include <functional>
 #include <memory>
 #include <initializer_list>

+ 109 - 44
pretty-print.py

@@ -28,13 +28,13 @@ class vectorPrinter:
         self.val = val
 
     def to_string(self):
-        return "vector of size %d, capacity %d" % (self.val['m_size'], self.val['m_capacity'])
+        return "std::vector of size %d, capacity %d" % (self.val['m_size'], self.val['m_capacity'])
 
     def display_hint(self):
         return 'array'
 
     def children(self):
-        return self._iterator(self.val['m_arr'], self.val['m_arr'] + self.val['m_size'], 0)
+        return self._iterator(self.val['m_data'], self.val['m_data'] + self.val['m_size'], 0)
 
 def _leftmost(node):
     ret = node
@@ -60,25 +60,28 @@ def _next(node):
                 break
         return ret['parent'].dereference()
 
-class mapPrinter:
-    def __init__(self, val):
-        self.val = val
+class rbtreePrinter:
+    def __init__(self, type, val):
+        self.type = type
+        self.val = val['tree']
 
     def to_string(self):
-        return "types::map"
+        return "%s of size %d" % (self.type, self.val['_size'])
 
     def display_hint(self):
         return 'array'
 
     def children(self):
-        yield '[root]', self.val['root']
+        yield 'root', self.val['root']
         if self.val['root'] == 0:
             return
 
+        yield 'size', self.val['_size']
+
         nd = _leftmost(self.val['root'].dereference())
         i = 0
         while True:
-            yield "[%d]" % i, nd['v']
+            yield "[%d]" % i, nd['value']
             nd = _next(nd)
             i += 1
             if nd == None:
@@ -89,17 +92,17 @@ class stringPrinter:
         self.val = val
     
     def to_string(self):
-        return self.val['m_arr']
+        return self.val['m_data']
     
     def children(self):
-        yield 'str', self.val['m_arr']
+        yield 'str', self.val['m_data']
 
-        if self.val['m_arr'] == 0:
+        if self.val['m_data'] == 0:
             return
 
         yield 'length', self.val['m_size'] - 1
 
-        ptr = self.val['m_arr']
+        ptr = self.val['m_data']
         i = 0
 
         while ptr.dereference() != 0:
@@ -114,25 +117,23 @@ class listPrinter:
         self.val = val
     
     def to_string(self):
-        return "list of size %d" % (self.val['head'].reinterpret_cast(gdb.lookup_type("size_t").pointer()) + 2).dereference()
+        return "std::list of size %d" % self.val['m_size']
 
     def display_hint(self):
         return 'array'
 
     def children(self):
-        head = self.val['head']
-        end = self.val['tail']
+        head = self.val['m_head']
 
-        yield '[head]', head
-        yield '[tail]', end
-        
-        if head == 0 or end == 0:
-            return
+        yield 'head', head.address
 
         node = head['next']
         idx = 0
-        while node != end:
-            yield '[%d]' % idx, node['value']
+        while node != head.address:
+            nodeval = node.reinterpret_cast(
+                gdb.lookup_type(self.val.type.unqualified().strip_typedefs().tag + '::node').pointer()
+                )
+            yield '[%d]' % idx, nodeval['value']
             idx += 1
             node = node['next']
 
@@ -141,31 +142,80 @@ class listIteratorPrinter:
         self.val = val
     
     def children(self):
-        yield '[addr]', self.val['n']
-        if self.val['n'] == 0:
+        yield 'addr', self.val['p']
+        if self.val['p'] == 0:
             return
+        
+        nodeptr = self.val['p']
+        iter_type = self.val.type.unqualified().strip_typedefs().tag
+        iter_type = iter_type[:iter_type.rfind('::')]
+        nodeptr = nodeptr.cast(gdb.lookup_type(iter_type + '::node').pointer())
+        
+        yield 'value', nodeptr['value']
 
-        for field in self.val['n']['value'].type.fields():
-            yield field.name, self.val['n']['value'][field.name]
-
-class mapIteratorPrinter:
+class rbtreeIteratorPrinter:
     def __init__(self, val):
         self.val = val
     
     def children(self):
-        yield '[addr]', self.val['p']
+        yield 'addr', self.val['p']
         if self.val['p'] == 0:
             return
         
-        yield '[first]', self.val['p']['v']['first']
-        yield '[second]', self.val['p']['v']['second']
+        yield 'value', self.val['p']['value']
 
 class vectorIteratorPrinter:
     def __init__(self, val):
         self.val = val
     
     def children(self):
-        yield 'value', self.val['p'].dereference()
+        yield 'value', self.val['m_ptr'].dereference()
+
+class pairPrinter:
+    def __init__(self, val):
+        self.val = val
+    
+    def children(self):
+        yield 'first', self.val['first']
+        yield 'second', self.val['second']
+
+class tuplePrinter:
+    def __init__(self, val):
+        self.val = val
+    
+    def children(self):
+        i = 0
+        try:
+            cur = self.val
+            while True:
+                yield '<%d>' % i, cur['val']
+                i += 1
+                cur = cur['next']
+        except Exception:
+            if i == 0:
+                yield 'tuple of size 0', ''
+
+class functionPrinter:
+    def __init__(self, val):
+        self.val = val
+    
+    def to_string(self):
+        return self.val.type.tag
+    
+    def children(self):
+        print(self.val['_data'].type)
+        yield 'function data', self.val['_data']
+
+class referenceWrapperPrinter:
+    def __init__(self, val):
+        self.val = val
+    
+    def to_string(self):
+        return "std::reference_wrapper to %x" % self.val['_ptr']
+    
+    def children(self):
+        yield 'addr', self.val['_ptr'].cast(gdb.lookup_type('void').pointer())
+        yield 'reference', self.val['_ptr']
 
 def build_pretty_printer(val):
     type = val.type
@@ -180,30 +230,45 @@ def build_pretty_printer(val):
 
     if typename == None:
         return None
+    
+    if re.compile(r"^std::pair<.*, .*>$").match(typename):
+        return pairPrinter(val)
+    
+    if re.compile(r"^std::tuple<.*>$").match(typename):
+        return tuplePrinter(val)
 
-    if re.compile(r"^types::list<.*?>::node<.*?>$").match(typename):
-        return None
+    if re.compile(r"^std::function<.*>$").match(typename):
+        return functionPrinter(val)
+    
+    if re.compile(r"^std::reference_wrapper<.*>$").match(typename):
+        return referenceWrapperPrinter(val)
 
-    if re.compile(r"^types::map<.*?,.*?,.*?>::iterator<.*?>$").match(typename):
-        return mapIteratorPrinter(val)
+    # if re.compile(r"^std::list<.*, .*>::node$").match(typename):
+    #     return None
     
-    if re.compile(r"^types::list<.*?>::iterator<.*?>$").match(typename):
+    if re.compile(r"^std::list<.*, .*>::_iterator<.*?>$").match(typename):
         return listIteratorPrinter(val)
 
-    if re.compile(r"^types::vector<.*?>::iterator<.*?>$").match(typename):
+    if re.compile(r"^std::vector<.*, .*>::_iterator<.*?>$").match(typename):
         return vectorIteratorPrinter(val)
 
-    if re.compile(r"^types::list<.*?>$").match(typename):
+    if re.compile(r"^std::list<.*, .*>$").match(typename):
         return listPrinter(val)
 
-    if re.compile(r"^types::vector<.*?>$").match(typename):
+    if re.compile(r"^std::vector<.*, .*>$").match(typename):
         return vectorPrinter(val)
 
-    if re.compile(r"^types::string<.*?>$").match(typename):
-        return stringPrinter(val)
+    if re.compile(r"^std::map<.*, .*, .*, .*>$").match(typename):
+        return rbtreePrinter("std::map", val)
+
+    if re.compile(r"^std::set<.*, .*, .*>$").match(typename):
+        return rbtreePrinter("std::set", val)
 
-    if re.compile(r"^types::map<.*?>$").match(typename):
-        return mapPrinter(val)
+    if re.compile(r"^std::impl::rbtree<.*, .*, .*>::_iterator<.*?>$").match(typename):
+        return rbtreeIteratorPrinter(val)
+
+    if re.compile(r"^types::string<.*>$").match(typename):
+        return stringPrinter(val)
     
     return None