RPA Toolkit
work on rmap_t - 3
authorMartin Stoilov <martin@rpasearch.com>
Thu, 9 Jun 2011 04:12:45 +0000 (21:12 -0700)
committerMartin Stoilov <martin@rpasearch.com>
Thu, 9 Jun 2011 04:12:45 +0000 (21:12 -0700)
rlib/rmap.c
rlib/rmap.h
rvm/rvmcpu.c
rvm/rvmoperatoradd.c
tests/testmisc/rmap-test.c

index 5190c78..76cf038 100644 (file)
@@ -8,6 +8,7 @@ typedef struct r_mapnode_s {
        rlink_t active;
        rlink_t hash;
        rsize_t index;
+       rlong nbucket;
        rstr_t *key;
        union {
                rpointer p;
@@ -74,10 +75,12 @@ void r_map_cleanup(robject_t *obj)
 
        while (!r_list_empty(&map->active)) {
                node = r_list_entry(r_list_first(&map->active), r_mapnode_t, active);
+               r_free(node->key);
                r_list_del(&node->active);
        }
        while (!r_list_empty(&map->inactive)) {
                node = r_list_entry(r_list_first(&map->inactive), r_mapnode_t, active);
+               r_free(node->key);
                r_list_del(&node->active);
        }
 
@@ -131,12 +134,12 @@ void r_map_destroy(rmap_t *map)
 rlong r_map_add(rmap_t *map, const rchar *name, rsize_t namesize, rconstpointer pval)
 {
        r_mapnode_t *node;
-       rulong nbucket;
 
        node = r_map_getfreenode(map, name, namesize);
-       r_memcpy(node->value.data, pval, map->elt_size);
-       nbucket = (r_map_rstrhash(node->key) & r_map_hashmask(map));
-       r_list_addt(&map->hash[nbucket], &node->hash);
+       if (pval)
+               r_memcpy(node->value.data, pval, map->elt_size);
+       node->nbucket = (r_map_rstrhash(node->key) & r_map_hashmask(map));
+       r_list_addt(&map->hash[node->nbucket], &node->hash);
        r_list_addt(&map->active, &node->active);
        return node->index;
 }
@@ -148,15 +151,19 @@ rlong r_map_add_s(rmap_t *map, const rchar *name, rconstpointer pval)
 }
 
 
-r_mapnode_t *r_map_node(rmap_t *map, rsize_t index)
+r_mapnode_t *r_map_node(rmap_t *map, rulong index)
 {
        r_mapnode_t *node;
+       if (index >= r_carray_length(map->data))
+               return NULL;
        node = (r_mapnode_t*)r_carray_slot(map->data, index);
+       if (r_list_empty(&node->hash))
+               return NULL;
        return node;
 }
 
 
-const rchar *r_map_key(rmap_t *map, rsize_t index)
+const rchar *r_map_key(rmap_t *map, rulong index)
 {
        r_mapnode_t *node = r_map_node(map, index);
        if (!node)
@@ -165,7 +172,7 @@ const rchar *r_map_key(rmap_t *map, rsize_t index)
 }
 
 
-rpointer r_map_value(rmap_t *map, rsize_t index)
+rpointer r_map_value(rmap_t *map, rulong index)
 {
        r_mapnode_t *node = r_map_node(map, index);
        if (!node)
@@ -174,7 +181,17 @@ rpointer r_map_value(rmap_t *map, rsize_t index)
 }
 
 
-rint r_map_delete(rmap_t *map, rsize_t index)
+rlong r_map_setvalue(rmap_t *map, rlong index, rconstpointer pval)
+{
+       r_mapnode_t *node = r_map_node(map, index);
+       if (!node)
+               return -1;
+       r_memcpy(node->value.data, pval, map->elt_size);
+       return index;
+}
+
+
+rint r_map_delete(rmap_t *map, rulong index)
 {
        r_mapnode_t *node = r_map_node(map, index);
        if (!node)
@@ -182,7 +199,140 @@ rint r_map_delete(rmap_t *map, rsize_t index)
        r_free(node->key);
        node->key = NULL;
        r_list_del(&node->hash);
+       r_list_init(&node->hash);
        r_list_del(&node->active);
        r_list_addt(&map->inactive, &node->active);
        return 0;
 }
+
+
+rlong r_map_lookup(rmap_t *map, rlong current, const rchar *name, rsize_t namesize)
+{
+       rlong found = -1;
+       r_mapnode_t *node;
+       rstr_t lookupstr = {(char*)name, namesize};
+       rulong nbucket;
+       rhead_t *bucket;
+       rlink_t *pos;
+
+       if (current >= 0) {
+               r_mapnode_t *curnode = r_map_node(map, current);
+               if (!curnode)
+                       return -1;
+               nbucket = curnode->nbucket;
+               bucket = &map->hash[nbucket];
+               pos = r_list_next(bucket, &curnode->hash);
+       } else {
+               nbucket = (r_map_rstrhash(&lookupstr) & r_map_hashmask(map));
+               bucket = &map->hash[nbucket];
+               pos = r_list_first(bucket);
+       }
+       for ( ; pos ; pos = r_list_next(bucket, pos)) {
+               node = r_list_entry(pos, r_mapnode_t, hash);
+               if (r_map_rstrequal(node->key, &lookupstr)) {
+                       found = node->index;
+                       break;
+               }
+       }
+
+       return (rlong)found;
+}
+
+
+rlong r_map_lookup_s(rmap_t *map, rlong current, const rchar *name)
+{
+       return r_map_lookup(map, current, name, r_strlen(name));
+}
+
+
+rlong r_map_taillookup(rmap_t *map, rlong current, const rchar *name, rsize_t namesize)
+{
+       rlong found = -1;
+       r_mapnode_t *node;
+       rstr_t lookupstr = {(char*)name, namesize};
+       rulong nbucket;
+       rhead_t *bucket;
+       rlink_t *pos;
+
+       if (current >= 0) {
+               r_mapnode_t *curnode = r_map_node(map, current);
+               if (!curnode)
+                       return -1;
+               nbucket = curnode->nbucket;
+               bucket = &map->hash[nbucket];
+               pos = r_list_prev(bucket, &curnode->hash);
+       } else {
+               nbucket = (r_map_rstrhash(&lookupstr) & r_map_hashmask(map));
+               bucket = &map->hash[nbucket];
+               pos = r_list_last(bucket);
+       }
+       for ( ; pos ; pos = r_list_prev(bucket, pos)) {
+               node = r_list_entry(pos, r_mapnode_t, hash);
+               if (r_map_rstrequal(node->key, &lookupstr)) {
+                       found = node->index;
+                       break;
+               }
+       }
+
+       return (rlong)found;
+}
+
+
+rlong r_map_taillookup_s(rmap_t *map, rlong current, const rchar *name)
+{
+       return r_map_taillookup(map, current, name, r_strlen(name));
+}
+
+
+rlong r_map_first(rmap_t *map)
+{
+       r_mapnode_t *node;
+       rlink_t *pos = r_list_first(&map->active);
+
+       if (!pos)
+               return -1;
+       node = r_list_entry(pos, r_mapnode_t, active);
+       return node->index;
+}
+
+
+rlong r_map_last(rmap_t *map)
+{
+       r_mapnode_t *node;
+       rlink_t *pos = r_list_last(&map->active);
+
+       if (!pos)
+               return -1;
+       node = r_list_entry(pos, r_mapnode_t, active);
+       return node->index;
+}
+
+
+rlong r_map_next(rmap_t *map, rlong current)
+{
+       r_mapnode_t *node = r_map_node(map, current);
+       rlink_t *pos;
+
+       if (!node)
+               return -1;
+       pos = r_list_next(&map->active, &node->active);
+       if (!pos)
+               return -1;
+       node = r_list_entry(pos, r_mapnode_t, active);
+       return node->index;
+}
+
+
+rlong r_map_prev(rmap_t *map, rlong current)
+{
+       r_mapnode_t *node = r_map_node(map, current);
+       rlink_t *pos;
+
+       if (!node)
+               return -1;
+       pos = r_list_prev(&map->active, &node->active);
+       if (!pos)
+               return -1;
+       node = r_list_entry(pos, r_mapnode_t, active);
+       return node->index;
+}
index f791e98..1bf5a51 100644 (file)
@@ -28,13 +28,21 @@ typedef struct rmap_s {
 
 rmap_t *r_map_create(ruint elt_size, ruint nbits);
 void r_map_destroy(rmap_t *array);
+rlong r_map_lookup(rmap_t *map, rlong current, const rchar *name, rsize_t namesize);
+rlong r_map_lookup_s(rmap_t *map, rlong current, const rchar *name);
+rlong r_map_taillookup(rmap_t *map, rlong current, const rchar *name, rsize_t namesize);
+rlong r_map_taillookup_s(rmap_t *map, rlong current, const rchar *name);
 rlong r_map_add(rmap_t *map, const rchar *name, rsize_t namesize, rconstpointer pval);
 rlong r_map_add_s(rmap_t *map, const rchar *name, rconstpointer pval);
-rlong r_map_replace(rmap_t *map, const rchar *name, rsize_t namesize, rconstpointer pval);
-rlong r_map_replace_s(rmap_t *map, const rchar *name, rconstpointer pval);
-const rchar *r_map_key(rmap_t *map, rsize_t index);
-rpointer r_map_value(rmap_t *map, rsize_t index);
-rint r_map_delete(rmap_t *map, rsize_t index);
+rlong r_map_setvalue(rmap_t *map, rlong index, rconstpointer pval);
+const rchar *r_map_key(rmap_t *map, rulong index);
+rpointer r_map_value(rmap_t *map, rulong index);
+rint r_map_delete(rmap_t *map, rulong index);
+
+rlong r_map_first(rmap_t *map);
+rlong r_map_last(rmap_t *map);
+rlong r_map_next(rmap_t *map, rlong current);
+rlong r_map_prev(rmap_t *map, rlong current);
 
 
 #ifdef __cplusplus
index 1b2b794..9d3d649 100644 (file)
@@ -30,6 +30,7 @@
 #include "rmem.h"
 #include "rstring.h"
 #include "rvmreg.h"
+#include "rmap.h"
 #include "rjsobject.h"
 
 #define RVM_DEFAULT_STACKSIZE (4 * 1024)
@@ -1518,7 +1519,7 @@ static void rvm_op_allocstr(rvmcpu_t *cpu, rvm_asmins_t *ins)
 static void rvm_op_allocobj(rvmcpu_t *cpu, rvm_asmins_t *ins)
 {
        rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
-       rjs_object_t *a = rjs_object_create(sizeof(rvmreg_t));
+       rmap_t *a = r_map_create(sizeof(rvmreg_t), 7);
        if (!a) {
                RVM_ABORT(cpu, RVM_E_ILLEGAL);
        }
@@ -1547,7 +1548,7 @@ static void rvm_op_addrobjn(rvmcpu_t *cpu, rvm_asmins_t *ins)
        rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
        rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
        rvmreg_t tmp = rvm_reg_create_long(0);
-       rjs_object_t *a;
+       rmap_t *a;
        rlong index;
 
        rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
@@ -1556,10 +1557,10 @@ static void rvm_op_addrobjn(rvmcpu_t *cpu, rvm_asmins_t *ins)
                RVM_ABORT(cpu, RVM_E_NOTOBJECT);
        if (index < 0)
                RVM_ABORT(cpu, RVM_E_ILLEGAL);
-       a = (rjs_object_t*)RVM_REG_GETP(arg2);
+       a = (rmap_t*)RVM_REG_GETP(arg2);
        RVM_REG_CLEAR(arg1);
        RVM_REG_SETTYPE(arg1, RVM_DTYPE_POINTER);
-       RVM_REG_SETP(arg1, r_carray_slot_expand(a->narray, index));
+       RVM_REG_SETP(arg1, r_map_value(a, index));
 }
 
 
@@ -1568,7 +1569,7 @@ static void rvm_op_ldobjn(rvmcpu_t *cpu, rvm_asmins_t *ins)
        rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
        rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
        rvmreg_t tmp = rvm_reg_create_long(0);
-       rjs_object_t *a = NULL;
+       rmap_t *a = NULL;
        rlong index;
 
        rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
@@ -1577,8 +1578,8 @@ static void rvm_op_ldobjn(rvmcpu_t *cpu, rvm_asmins_t *ins)
                RVM_ABORT(cpu, RVM_E_NOTOBJECT);
        if (index < 0)
                RVM_ABORT(cpu, RVM_E_ILLEGAL);
-       a = (rjs_object_t*)RVM_REG_GETP(arg2);
-       *arg1 = *((rvmreg_t*)r_carray_slot_expand(a->narray, index));
+       a = (rmap_t*)RVM_REG_GETP(arg2);
+       *arg1 = *((rvmreg_t*)r_map_value(a, index));
 }
 
 
@@ -1587,7 +1588,7 @@ static void rvm_op_stobjn(rvmcpu_t *cpu, rvm_asmins_t *ins)
        rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
        rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
        rvmreg_t tmp = rvm_reg_create_long(0);
-       rjs_object_t *a = NULL;
+       rmap_t *a = NULL;
        rlong index;
 
        rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
@@ -1596,8 +1597,8 @@ static void rvm_op_stobjn(rvmcpu_t *cpu, rvm_asmins_t *ins)
                RVM_ABORT(cpu, RVM_E_NOTOBJECT);
        if (index < 0)
                RVM_ABORT(cpu, RVM_E_ILLEGAL);
-       a = (rjs_object_t*)RVM_REG_GETP(arg2);
-       r_carray_replace(a->narray, index, arg1);
+       a = (rmap_t*)RVM_REG_GETP(arg2);
+       r_map_setvalue(a, index, arg1);
 }
 
 
@@ -1606,12 +1607,12 @@ static void rvm_op_objlookup(rvmcpu_t *cpu, rvm_asmins_t *ins)
        rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
        rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
        rlong index;
-       rjs_object_t *a = (rjs_object_t*)RVM_REG_GETP(arg2);
+       rmap_t *a = (rmap_t*)RVM_REG_GETP(arg2);
 
        if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT) {
                RVM_ABORT(cpu, RVM_E_NOTOBJECT);
        }
-       index = r_harray_lookup(a->harray, RVM_CPUREG_GETP(cpu, ins->op3), RVM_CPUREG_GETL(cpu, ins->op1));
+       index = r_map_lookup(a, -1, RVM_CPUREG_GETP(cpu, ins->op3), RVM_CPUREG_GETL(cpu, ins->op1));
 
        RVM_REG_CLEAR(arg1);
        RVM_REG_SETTYPE(arg1, RVM_DTYPE_LONG);
@@ -1624,12 +1625,12 @@ static void rvm_op_objkeyadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
        rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
        rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
        rlong index;
-       rjs_object_t *a = (rjs_object_t*)RVM_REG_GETP(arg2);
+       rmap_t *a = (rmap_t*)RVM_REG_GETP(arg2);
 
        if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT) {
                RVM_ABORT(cpu, RVM_E_NOTOBJECT);
        }
-       index = r_harray_add(a->harray, RVM_CPUREG_GETP(cpu, ins->op3), RVM_CPUREG_GETL(cpu, ins->op1), NULL);
+       index = r_map_add(a, RVM_CPUREG_GETP(cpu, ins->op3), RVM_CPUREG_GETL(cpu, ins->op1), NULL);
 
        RVM_REG_CLEAR(arg1);
        RVM_REG_SETTYPE(arg1, RVM_DTYPE_LONG);
@@ -1642,14 +1643,14 @@ static void rvm_op_objkeylookupadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
        rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
        rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
        rlong index;
-       rjs_object_t *a = (rjs_object_t*)RVM_REG_GETP(arg2);
+       rmap_t *a = (rmap_t*)RVM_REG_GETP(arg2);
 
        if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT) {
                RVM_ABORT(cpu, RVM_E_NOTOBJECT);
        }
-       index = r_harray_lookup(a->harray, RVM_CPUREG_GETP(cpu, ins->op3), RVM_CPUREG_GETL(cpu, ins->op1));
+       index = r_map_lookup(a, -1, RVM_CPUREG_GETP(cpu, ins->op3), RVM_CPUREG_GETL(cpu, ins->op1));
        if (index < 0)
-               index = r_harray_add(a->harray, RVM_CPUREG_GETP(cpu, ins->op3), RVM_CPUREG_GETL(cpu, ins->op1), NULL);
+               index = r_map_add(a, RVM_CPUREG_GETP(cpu, ins->op3), RVM_CPUREG_GETL(cpu, ins->op1), NULL);
 
        RVM_REG_CLEAR(arg1);
        RVM_REG_SETTYPE(arg1, RVM_DTYPE_LONG);
@@ -1662,19 +1663,21 @@ static void rvm_op_addrobjh(rvmcpu_t *cpu, rvm_asmins_t *ins)
        rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
        rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
        rvmreg_t tmp = rvm_reg_create_long(0);
-       rjs_object_t *a;
+       rmap_t *a;
+       rpointer value;
        rlong index;
 
        rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
        index = RVM_REG_GETL(&tmp);
        if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT)
                RVM_ABORT(cpu, RVM_E_NOTOBJECT);
-       if (index < 0)
+       a = (rmap_t*)RVM_REG_GETP(arg2);
+       value = r_map_value(a, index);
+       if (!value)
                RVM_ABORT(cpu, RVM_E_ILLEGAL);
-       a = (rjs_object_t*)RVM_REG_GETP(arg2);
        RVM_REG_CLEAR(arg1);
        RVM_REG_SETTYPE(arg1, RVM_DTYPE_POINTER);
-       RVM_REG_SETP(arg1, r_carray_slot_expand(a->harray->members, index));
+       RVM_REG_SETP(arg1, value);
 }
 
 
@@ -1683,19 +1686,21 @@ static void rvm_op_ldobjh(rvmcpu_t *cpu, rvm_asmins_t *ins)
        rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
        rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
        rvmreg_t tmp = rvm_reg_create_long(0);
-       rjs_object_t *a = NULL;
+       rmap_t *a = NULL;
+       rpointer value;
        rlong index;
 
        rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
        index = RVM_REG_GETL(&tmp);
        if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT)
                RVM_ABORT(cpu, RVM_E_NOTOBJECT);
-       a = (rjs_object_t*)RVM_REG_GETP(arg2);
-       if (index < 0) {
+       a = (rmap_t*)RVM_REG_GETP(arg2);
+       value = r_map_value(a, index);
+       if (!value) {
                RVM_REG_CLEAR(arg1);
                RVM_REG_SETTYPE(arg1, RVM_DTYPE_UNDEF);
        } else {
-               *arg1 = *((rvmreg_t*)r_carray_slot_expand(a->harray->members, index));
+               *arg1 = *((rvmreg_t*)value);
        }
 }
 
@@ -1705,17 +1710,19 @@ static void rvm_op_stobjh(rvmcpu_t *cpu, rvm_asmins_t *ins)
        rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
        rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
        rvmreg_t tmp = rvm_reg_create_long(0);
-       rjs_object_t *a = NULL;
+       rmap_t *a = NULL;
+       rpointer value;
        rlong index;
 
        rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
        index = RVM_REG_GETL(&tmp);
        if (rvm_reg_gettype(arg2) != RVM_DTYPE_JSOBJECT)
                RVM_ABORT(cpu, RVM_E_NOTOBJECT);
-       if (index < 0)
+       a = (rmap_t*)RVM_REG_GETP(arg2);
+       value = r_map_value(a, index);
+       if (!value)
                RVM_ABORT(cpu, RVM_E_ILLEGAL);
-       a = (rjs_object_t*)RVM_REG_GETP(arg2);
-       r_carray_replace(a->harray->members, index, arg1);
+       r_map_setvalue(a, index, arg1);
 }
 
 
index 33a17ce..bccb1f5 100644 (file)
@@ -90,7 +90,7 @@ void rvm_op_concat_double_string(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, con
 void rvm_op_concat_string_double(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
 {
        rstring_t *s1 = (rstring_t *)RVM_REG_GETP(arg1);
-       rstring_t *s2 = r_string_create_from_long(RVM_REG_GETD(arg2));
+       rstring_t *s2 = r_string_create_from_double(RVM_REG_GETD(arg2));
        rstring_t *d = r_string_create_from_rstr(&s1->s);
        r_string_cat(d, &s2->s);
        r_object_destroy((robject_t*)s2);
index 6a4012b..5d8e0cc 100644 (file)
@@ -11,7 +11,7 @@ rlong test_rmap_add(rmap_t *map, const rchar *name, rlong val)
 }
 
 
-void test_rmap_print(rmap_t * map, rsize_t index)
+void test_rmap_print(rmap_t * map, rulong index)
 {
        if (r_map_value(map, index))
                fprintf(stdout, "(Index: %3ld) Key: %s, Value: %ld\n", index, r_map_key(map, index), *((rlong*)r_map_value(map, index)));
@@ -20,8 +20,34 @@ void test_rmap_print(rmap_t * map, rsize_t index)
 }
 
 
+void test_rmap_lookup(rmap_t * map, const rchar *name)
+{
+       rlong index = -1;
+
+       do {
+               index = r_map_lookup_s(map, index, name);
+               if (index >= 0)
+                       fprintf(stdout, "(Lookup index: %3ld) Key: %s, Value: %ld\n", index, r_map_key(map, index), *((rlong*)r_map_value(map, index)));
+       } while (index >= 0);
+}
+
+
+void test_rmap_taillookup(rmap_t * map, const rchar *name)
+{
+       rlong index = -1;
+
+       do {
+               index = r_map_taillookup_s(map, index, name);
+               if (index >= 0)
+                       fprintf(stdout, "(Tail Lookup index: %3ld) Key: %s, Value: %ld\n", index, r_map_key(map, index), *((rlong*)r_map_value(map, index)));
+       } while (index >= 0);
+
+}
+
+
 int main(int argc, char *argv[])
 {
+       rlong l, val = 17;
        rmap_t *map = r_map_create(sizeof(rlong), 7);
 
        test_rmap_add(map, "one", 1);
@@ -30,12 +56,31 @@ int main(int argc, char *argv[])
        r_map_delete(map, 1);
        r_map_delete(map, 1);
        test_rmap_add(map, "four", 4);
+       test_rmap_add(map, "four", 5);
+       test_rmap_add(map, "four", 9);
 
        test_rmap_print(map, 0);
        test_rmap_print(map, 1);
        test_rmap_print(map, 2);
        test_rmap_print(map, 3);
 
+       test_rmap_lookup(map, "four");
+       r_map_setvalue(map, r_map_lookup_s(map, -1, "four"), &val);
+       test_rmap_taillookup(map, "four");
+
+       for (l = r_map_first(map); l >= 0; l = r_map_next(map, l)) {
+               test_rmap_print(map, l);
+       }
+
+       test_rmap_add(map, "three", 13);
+       test_rmap_add(map, NULL, 23);
+       test_rmap_add(map, "four", 44);
+       test_rmap_add(map, "three", 33);
+
+       for (l = r_map_first(map); l >= 0; l = r_map_next(map, l)) {
+               test_rmap_print(map, l);
+       }
+
        r_map_destroy(map);
 
        fprintf(stdout, "Max alloc mem: %ld\n", r_debug_get_maxmem());