diff --git a/libc3/buf_parse.c b/libc3/buf_parse.c
index 538fd5f..4a49795 100644
--- a/libc3/buf_parse.c
+++ b/libc3/buf_parse.c
@@ -1859,6 +1859,7 @@ sw buf_parse_map (s_buf *buf, s_map *dest)
buf_save_init(buf, &save);
if ((r = buf_read_1(buf, "%{")) <= 0)
goto clean;
+ result += r;
keys = NULL;
keys_end = &keys;
values = NULL;
diff --git a/libc3/compare.c b/libc3/compare.c
index b3ee036..1d15169 100644
--- a/libc3/compare.c
+++ b/libc3/compare.c
@@ -298,6 +298,27 @@ s8 compare_list (const s_list *a, const s_list *b)
}
}
+s8 compare_map (const s_map *a, const s_map *b)
+{
+ uw i = 0;
+ s8 r;
+ assert(a);
+ assert(b);
+ if (a == b)
+ return 0;
+ if (a->count < b->count)
+ return -1;
+ if (a->count > b->count)
+ return 1;
+ while (i < a->count) {
+ if ((r = compare_tag(a->keys + i, b->keys + i)) ||
+ (r = compare_tag(a->values + i, b->values + i)))
+ return r;
+ i++;
+ }
+ return 0;
+}
+
s8 compare_ptag (const p_tag a, const p_tag b)
{
if (a < b)
@@ -777,6 +798,7 @@ s8 compare_tag (const s_tag *a, const s_tag *b) {
case TAG_FN: return compare_fn(&a->data.fn, &b->data.fn);
case TAG_IDENT: return compare_ident(&a->data.ident, &b->data.ident);
case TAG_LIST: return compare_list(a->data.list, b->data.list);
+ case TAG_MAP: return compare_map(&a->data.map, &b->data.map);
case TAG_PTAG: return compare_ptag(a->data.ptag, b->data.ptag);
case TAG_QUOTE: return compare_quote(&a->data.quote, &b->data.quote);
case TAG_STR: return compare_str(&a->data.str, &b->data.str);
diff --git a/libc3/compare.h b/libc3/compare.h
index 561908a..2504285 100644
--- a/libc3/compare.h
+++ b/libc3/compare.h
@@ -36,6 +36,7 @@ s8 compare_integer (const s_integer *a, const s_integer *b);
s8 compare_integer_s64 (const s_integer *a, s64 b);
s8 compare_integer_u64 (const s_integer *a, u64 b);
s8 compare_list (const s_list *a, const s_list *b);
+s8 compare_map (const s_map *a, const s_map *b);
s8 compare_ptag (const p_tag a, const p_tag b);
s8 compare_quote (const s_quote *a, const s_quote *b);
COMPARE_PROTOTYPE(s8);
diff --git a/libc3/list.c b/libc3/list.c
index 7677e9e..3f1f3c7 100644
--- a/libc3/list.c
+++ b/libc3/list.c
@@ -26,7 +26,7 @@ s_list * list_1 (const char *p)
s_buf buf;
s_list *list;
buf_init_1(&buf, p);
- if (buf_parse_list(&buf, &list) <= 0) {
+ if (buf_parse_list(&buf, &list) != (sw) strlen(p)) {
assert(! "invalid list");
buf_clean(&buf);
return NULL;
diff --git a/libc3/map.c b/libc3/map.c
index 47c5f77..0905204 100644
--- a/libc3/map.c
+++ b/libc3/map.c
@@ -13,6 +13,9 @@
#include <assert.h>
#include <err.h>
#include <stdlib.h>
+#include <string.h>
+#include "buf.h"
+#include "buf_parse.h"
#include "compare.h"
#include "list.h"
#include "map.h"
@@ -78,6 +81,23 @@ s_map * map_init (s_map *map, uw count)
return map;
}
+s_map * map_init_1 (s_map *map, const s8 *p)
+{
+ s_buf buf;
+ sw r;
+ assert(map);
+ assert(p);
+ buf_init_1(&buf, p);
+ if ((r = buf_parse_map(&buf, map)) != (sw) strlen(p)) {
+ assert(! "invalid map");
+ warnx("invalid map: \"%s\" (%ld)", p, r);
+ buf_clean(&buf);
+ return NULL;
+ }
+ buf_clean(&buf);
+ return map;
+}
+
s_map * map_init_from_lists (s_map *map, const s_list *keys,
const s_list *values)
{
@@ -119,6 +139,16 @@ s_map * map_new (uw count)
return map_init(map, count);
}
+s_map * map_new_1 (const s8 *p)
+{
+ s_map *map;
+ if (! (map = malloc(sizeof(s_map)))) {
+ warn("map_new");
+ return NULL;
+ }
+ return map_init_1(map, p);
+}
+
s_map * map_new_from_lists (const s_list *keys, const s_list *values)
{
s_map *map;
diff --git a/libc3/map.h b/libc3/map.h
index 355ea6f..9025dcc 100644
--- a/libc3/map.h
+++ b/libc3/map.h
@@ -18,12 +18,14 @@
/* Stack allocation compatible functions, call map_clean after use. */
void map_clean (s_map *map);
s_map * map_init (s_map *map, uw size);
+s_map * map_init_1 (s_map *map, const s8 *p);
s_map * map_init_from_lists (s_map *map, const s_list *keys,
const s_list *values);
/* Heap allocation functions, call map_delete after use. */
void map_delete (s_map *map);
s_map * map_new (uw size);
+s_map * map_new_1 (const s8 *p);
s_map * map_new_from_lists (const s_list *keys, const s_list *values);
/* Modifiers */
diff --git a/test/compare_test.c b/test/compare_test.c
index ac6e338..9caf0ff 100644
--- a/test/compare_test.c
+++ b/test/compare_test.c
@@ -12,6 +12,7 @@
*/
#include "compare_test.h"
#include "../libc3/list.h"
+#include "../libc3/map.h"
#include "../libc3/tag.h"
#include "../libc3/tuple.h"
@@ -26,6 +27,13 @@
test_context(NULL); \
} while (0)
+#define COMPARE_TEST_MAP(a, b, expected) \
+ do { \
+ test_context("compare_map(" # a ", " # b ") -> " # expected); \
+ TEST_EQ(compare_map((a), (b)), (expected)); \
+ test_context(NULL); \
+ } while (0)
+
#define COMPARE_TEST_TAG(a, b, expected) \
do { \
TEST_EQ(compare_tag((a), (b)), (expected)); \
@@ -43,6 +51,7 @@ TEST_CASE_PROTOTYPE(compare_character);
TEST_CASE_PROTOTYPE(compare_f32);
TEST_CASE_PROTOTYPE(compare_f64);
TEST_CASE_PROTOTYPE(compare_list);
+TEST_CASE_PROTOTYPE(compare_map);
TEST_CASE_PROTOTYPE(compare_str);
TEST_CASE_PROTOTYPE(compare_tag);
TEST_CASE_PROTOTYPE(compare_tuple);
@@ -54,6 +63,7 @@ void compare_test (void)
TEST_CASE_RUN(compare_f32);
TEST_CASE_RUN(compare_f64);
TEST_CASE_RUN(compare_list);
+ TEST_CASE_RUN(compare_map);
TEST_CASE_RUN(compare_str);
TEST_CASE_RUN(compare_tag);
TEST_CASE_RUN(compare_tuple);
@@ -145,6 +155,34 @@ TEST_CASE(compare_list)
}
TEST_CASE_END(compare_list)
+TEST_CASE(compare_map)
+{
+ s_map a;
+ s_map b;
+ COMPARE_TEST_MAP(map_init_1(&a, "%{a: A, b: B}"),
+ map_init_1(&b, "%{a: A, b: B}"), 0);
+ COMPARE_TEST_MAP(&a, &a, 0);
+ map_clean(&a);
+ map_clean(&b);
+ COMPARE_TEST_MAP(map_init_1(&a, "%{a: A, b: A}"),
+ map_init_1(&b, "%{a: A, b: B}"), -1);
+ map_clean(&a);
+ map_clean(&b);
+ COMPARE_TEST_MAP(map_init_1(&a, "%{a: A, b: B}"),
+ map_init_1(&b, "%{a: A, b: A}"), 1);
+ map_clean(&a);
+ map_clean(&b);
+ COMPARE_TEST_MAP(map_init_1(&a, "%{a: A, b: B}"),
+ map_init_1(&b, "%{a: A, b: B, c: C}"), -1);
+ map_clean(&a);
+ map_clean(&b);
+ COMPARE_TEST_MAP(map_init_1(&a, "%{a: A, b: B, c: C}"),
+ map_init_1(&b, "%{a: A, b: B}"), 1);
+ map_clean(&a);
+ map_clean(&b);
+}
+TEST_CASE_END(compare_map)
+
TEST_CASE(compare_str)
{
s_str *p;
diff --git a/test/compare_test.h b/test/compare_test.h
index 2c6c907..fa663d3 100644
--- a/test/compare_test.h
+++ b/test/compare_test.h
@@ -19,21 +19,22 @@
#define COMPARE_TEST_STR(a, b, expected) \
do { \
- const s_str *a_ = (a); \
- const s_str *b_ = (b); \
+ const s_str *a_ = (a); \
+ const s_str *b_ = (b); \
sw tmp = compare_str(a_, b_); \
if (tmp == expected) { \
- test_ok(); \
+ g_test_assert_count++; \
+ g_test_assert_ok++; \
} \
else { \
test_ko(); \
- printf("\n%sAssertion failed in %s:%d %s\n" \
- "compare_str(%s, %s) == %s\n" \
- "Expected %s got %ld.%s\n", \
- TEST_COLOR_KO, \
- __FILE__, __LINE__, __func__, \
- # a, # b, # expected, # expected, tmp, \
- TEST_COLOR_RESET); \
+ fprintf(stderr, "\n%sAssertion failed in %s:%d %s\n" \
+ "compare_str(%s, %s) == %s\n" \
+ "Expected %s got %ld.%s\n", \
+ TEST_COLOR_KO, \
+ __FILE__, __LINE__, __func__, \
+ # a, # b, # expected, # expected, tmp, \
+ TEST_COLOR_RESET); \
} \
} while (0)
diff --git a/test/ic3/map.in b/test/ic3/map.in
index 6eb013e..61f071f 100644
--- a/test/ic3/map.in
+++ b/test/ic3/map.in
@@ -50,3 +50,33 @@ quote %{b: b} = %{a: 1, b: 2}
%{b: b} = %{a: 1, b: 2}
quote b
b
+quote %{a: A, b: A} < %{a: A, b: A}
+%{a: A, b: A} < %{a: A, b: A}
+quote %{a: A, b: A} < %{a: A, c: A}
+%{a: A, b: A} < %{a: A, c: A}
+quote %{a: A, c: A} < %{a: A, b: A}
+%{a: A, c: A} < %{a: A, b: A}
+quote %{a: A, b: A} < %{a: A, b: B}
+%{a: A, b: A} < %{a: A, b: B}
+quote %{a: B, b: A} < %{a: A, b: A}
+%{a: B, b: A} < %{a: A, b: A}
+quote %{a: A, b: A} == %{a: A, b: A}
+%{a: A, b: A} == %{a: A, b: A}
+quote %{a: A, b: A} == %{a: A, c: A}
+%{a: A, b: A} == %{a: A, c: A}
+quote %{a: A, c: A} == %{a: A, b: A}
+%{a: A, c: A} == %{a: A, b: A}
+quote %{a: A, b: A} == %{a: A, b: B}
+%{a: A, b: A} == %{a: A, b: B}
+quote %{a: B, b: A} == %{a: A, b: A}
+%{a: B, b: A} == %{a: A, b: A}
+quote %{a: A, b: A} > %{a: A, b: A}
+%{a: A, b: A} > %{a: A, b: A}
+quote %{a: A, b: A} > %{a: A, c: A}
+%{a: A, b: A} > %{a: A, c: A}
+quote %{a: A, c: A} > %{a: A, b: A}
+%{a: A, c: A} > %{a: A, b: A}
+quote %{a: A, b: A} > %{a: A, b: B}
+%{a: A, b: A} > %{a: A, b: B}
+quote %{a: B, b: A} > %{a: A, b: A}
+%{a: B, b: A} > %{a: A, b: A}
diff --git a/test/ic3/map.out.expected b/test/ic3/map.out.expected
index 0cbf8ab..4deb429 100644
--- a/test/ic3/map.out.expected
+++ b/test/ic3/map.out.expected
@@ -50,3 +50,33 @@ a
%{a: 1, b: 2}
b
2
+%{a: A, b: A} < %{a: A, b: A}
+false
+%{a: A, b: A} < %{a: A, c: A}
+true
+%{a: A, c: A} < %{a: A, b: A}
+false
+%{a: A, b: A} < %{a: A, b: B}
+true
+%{a: B, b: A} < %{a: A, b: A}
+false
+%{a: A, b: A} == %{a: A, b: A}
+true
+%{a: A, b: A} == %{a: A, c: A}
+false
+%{a: A, c: A} == %{a: A, b: A}
+false
+%{a: A, b: A} == %{a: A, b: B}
+false
+%{a: B, b: A} == %{a: A, b: A}
+false
+%{a: A, b: A} > %{a: A, b: A}
+false
+%{a: A, b: A} > %{a: A, c: A}
+false
+%{a: A, c: A} > %{a: A, b: A}
+true
+%{a: A, b: A} > %{a: A, b: B}
+false
+%{a: B, b: A} > %{a: A, b: A}
+true