From 3fdd4046c4306256233984e289898f24324273f9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= <egil@erlang.org>
Date: Tue, 10 Mar 2015 09:04:56 +0100
Subject: erts: Add hashmap_iterator_prev to maps

---
 erts/emulator/beam/erl_map.c | 45 ++++++++++++++++++++++++++++++++++++++++++++
 erts/emulator/beam/erl_map.h |  1 +
 2 files changed, 46 insertions(+)

(limited to 'erts')

diff --git a/erts/emulator/beam/erl_map.c b/erts/emulator/beam/erl_map.c
index 5eafa69b06..65a31d3680 100644
--- a/erts/emulator/beam/erl_map.c
+++ b/erts/emulator/beam/erl_map.c
@@ -1758,6 +1758,51 @@ Eterm* hashmap_iterator_next(ErtsWStack* s) {
     }
 }
 
+Eterm* hashmap_iterator_prev(ErtsWStack* s) {
+    Eterm node, *ptr, hdr;
+    Uint32 sz,i;
+
+    for (;;) {
+        ASSERT(!WSTACK_ISEMPTY((*s)));
+	node = (Eterm) WSTACK_POP((*s));
+        if (is_non_value(node)) {
+            return NULL;
+        }
+        switch (primary_tag(node)) {
+        case TAG_PRIMARY_LIST:
+            return list_val(node);
+
+        case TAG_PRIMARY_BOXED:
+            ptr = boxed_val(node);
+            hdr = *ptr;
+            ASSERT(is_header(hdr));
+            switch(hdr & _HEADER_MAP_SUBTAG_MASK) {
+            case HAMT_SUBTAG_HEAD_ARRAY:
+                ptr++;
+            case HAMT_SUBTAG_NODE_ARRAY:
+                ptr++;
+                i = 0;
+                while(i < 16) { WSTACK_PUSH((*s), (UWord)ptr[i++]); }
+                break;
+            case HAMT_SUBTAG_HEAD_BITMAP:
+                ptr++;
+            case HAMT_SUBTAG_NODE_BITMAP:
+                sz = hashmap_bitcount(MAP_HEADER_VAL(hdr));
+                ASSERT(sz < 17);
+		i = 0;
+                ptr++;
+                while(i < sz) { WSTACK_PUSH((*s), (UWord)ptr[i++]); }
+                break;
+            default:
+                erl_exit(1, "bad header");
+            }
+            break;
+
+        default:
+            erl_exit(1, "bad hamt node");
+	}
+    }
+}
 const Eterm *erts_hashmap_get(Uint32 hx, Eterm key, Eterm node) {
     Eterm *ptr, hdr;
     Eterm th[2];
diff --git a/erts/emulator/beam/erl_map.h b/erts/emulator/beam/erl_map.h
index 659295184d..db22d461ce 100644
--- a/erts/emulator/beam/erl_map.h
+++ b/erts/emulator/beam/erl_map.h
@@ -102,6 +102,7 @@ int    erts_validate_and_sort_map(map_t* map);
 Uint   hashmap_over_estimated_heap_size(Uint n);
 void   hashmap_iterator_init(struct ErtsWStack_* s, Eterm node);
 Eterm* hashmap_iterator_next(struct ErtsWStack_* s);
+Eterm* hashmap_iterator_prev(struct ErtsWStack_* s);
 int    hashmap_key_hash_cmp(Eterm* ap, Eterm* bp);
 Eterm  erts_hashmap_from_array(ErtsHeapFactory*, Eterm *leafs, Uint n, int reject_dupkeys);
 const  Eterm *erts_hashmap_get(Uint32 hx, Eterm key, Eterm map);
-- 
cgit v1.2.3