Commit 3a34aa1a authored by Rusty Russell's avatar Rusty Russell

jmap: use ccan/tcon and always be typesafe.

This handles both pointer and integer types using ccan/tcon.
parent 805ea067
......@@ -9,38 +9,46 @@
* integers or pointers as an index, Judy arrays provide an efficient
* map to integers or pointers.
*
* jmap.h simply contains wrappers for a size_t-indexed size_t values, and
* jmap_type.h contain a wrapper macro for size_t->pointer maps and pointer
* ->pointer maps.
* You define a struct for your particular index and value types using
* the JMAP_MEMBERS macro, then use the jmap routines to manipulate
* the mapping.
*
* Note: if you use an integer type for the index or value types and
* your compiler doesn't support "typeof", you will get warnings about
* mixing pointers and integers.
*
* Example:
* // Silly example of associating data with arguments by pointer and int.
* #include <string.h>
* #include <stdio.h>
* #include <ccan/jmap/jmap_type.h>
* #include <ccan/jmap/jmap.h>
*
* struct opt_detail {
* bool is_long;
* unsigned int length; // == 1 if !is_long.
* };
*
* // Define jmap_arg_<op> and jmap_arg, for int -> argv.
* JMAP_DEFINE_UINTIDX_TYPE(char, arg);
* // Define jmap_opt_<op> and jmap_opt, for argv -> struct opt_detail *.
* JMAP_DEFINE_PTRIDX_TYPE(char, struct opt_detail, opt);
* // Define map type for int -> argv.
* struct arg_map {
* JMAP_MEMBERS(int, char *);
* };
* // Define map type for argv -> struct opt_detail *.
* struct opt_map {
* JMAP_MEMBERS(char *, struct opt_detail *);
* };
*
* int main(int argc, char *argv[])
* {
* int i;
* // This map is equivalent to the argv[] array. Silly example.
* struct jmap_arg *arg = jmap_arg_new();
* struct jmap_opt *opt = jmap_opt_new();
* struct arg_map *arg = jmap_new(struct arg_map);
* struct opt_map *opt = jmap_new(struct opt_map);
* struct opt_detail *d;
*
* // Note: this is not correct for real parsing!
* for (i = 0; i < argc; i++) {
* jmap_arg_add(arg, i, argv[i]);
* if (i < 1 || argv[i][0] != '-')
* for (i = 1; i < argc; i++) {
* jmap_add(arg, i, argv[i]);
* if (argv[i][0] != '-')
* continue;
* d = malloc(sizeof(*d));
* if (argv[i][1] == '-') {
......@@ -52,27 +60,30 @@
* d->is_long = false;
* d->length = 1;
* }
* jmap_opt_add(opt, argv[i], d);
* jmap_add(opt, argv[i], d);
* }
*
* printf("Found %lu options:\n", jmap_opt_count(opt));
* for (i = jmap_arg_first(arg,-1); i!=-1; i = jmap_arg_next(arg,i,-1)) {
* char *a = jmap_arg_get(arg, i);
* d = jmap_opt_get(opt, a);
* printf("Found %lu options:\n", jmap_count(opt));
* for (i = jmap_first(arg); i; i = jmap_next(arg,i)) {
* char *a = jmap_get(arg, i);
* d = jmap_get(opt, a);
* printf(" Arg %i ('%s') is a %s of %u chars\n",
* i, a,
* d == NULL ? "normal argument"
* : d->is_long ? "long option"
* : "short option",
* d == NULL ? "normal arg"
* : d->is_long ? "long opt"
* : "short opt",
* d == NULL ? strlen(a) : d->length);
* // We no longer need it, so free it here.
* free(d);
* }
* jmap_opt_free(opt);
* jmap_arg_free(arg);
* jmap_free(opt);
* jmap_free(arg);
* return 0;
* }
*
* // Given "--help" output contains "Arg 1 ('--help') is a long opt of 4 chars"
* // Given "-h" output contains "Arg 1 ('-h') is a short opt of 1 chars"
* // Given "foo" output contains "Arg 1 ('foo') is a normal arg of 3 chars"
*
* License: LGPL (v2.1 or any later version)
* Author: Rusty Russell <rusty@rustcorp.com.au>
*/
......@@ -84,6 +95,7 @@ int main(int argc, char *argv[])
if (strcmp(argv[1], "depends") == 0) {
printf("ccan/build_assert\n");
printf("ccan/compiler\n");
printf("ccan/tcon\n");
printf("Judy\n");
return 0;
}
......
......@@ -4,7 +4,7 @@
#include <stdlib.h>
#include <string.h>
struct jmap *jmap_new(void)
struct jmap *jmap_new_(size_t size)
{
struct jmap *map;
......@@ -13,7 +13,8 @@ struct jmap *jmap_new(void)
/* We also put pointers into Judy, in jmap_types.h */
BUILD_ASSERT(sizeof(Word_t) >= sizeof(void *));
map = malloc(sizeof(*map));
assert(size >= sizeof(*map));
map = malloc(size);
if (map) {
map->judy = NULL;
memset(&map->err, 0, sizeof(map->err));
......@@ -26,7 +27,7 @@ struct jmap *jmap_new(void)
return map;
}
const char *jmap_error_(struct jmap *map)
const char *jmap_error_str_(struct jmap *map)
{
char *str;
free((char *)map->errstr);
......@@ -40,7 +41,7 @@ const char *jmap_error_(struct jmap *map)
return str;
}
void jmap_free(const struct jmap *map)
void jmap_free_(const struct jmap *map)
{
free((char *)map->errstr);
JudyLFreeArray((PPvoid_t)&map->judy, PJE0);
......
This diff is collapsed.
This diff is collapsed.
......@@ -5,15 +5,19 @@
#include <sys/wait.h>
#include <unistd.h>
struct map {
JMAP_MEMBERS(unsigned long, unsigned long);
};
int main(int argc, char *argv[])
{
struct jmap *map;
struct map *map;
unsigned long *value;
int status;
plan_tests(9);
map = jmap_new();
map = jmap_new(struct map);
ok1(jmap_error(map) == NULL);
ok1(jmap_add(map, 0, 1));
......
#include <ccan/tap/tap.h>
#include <ccan/jmap/jmap.c>
struct idx;
struct map {
JMAP_MEMBERS(struct idx *, int);
};
#define NUM 100
static int cmp_ptr(const void *a, const void *b)
{
return *(char **)a - *(char **)b;
}
int main(int argc, char *argv[])
{
struct map *map;
struct idx *idx[NUM+1], *index;
unsigned int i;
int *intp;
plan_tests(25 + NUM*2 + 6);
for (i = 0; i < NUM+1; i++)
idx[i] = malloc(20);
qsort(idx, NUM, sizeof(idx[0]), cmp_ptr);
map = jmap_new(struct map);
ok1(jmap_error(map) == NULL);
ok1(jmap_test(map, idx[NUM]) == false);
ok1(jmap_get(map, idx[NUM]) == 0);
ok1(jmap_count(map) == 0);
ok1(jmap_first(map) == 0);
ok1(jmap_del(map, idx[0]) == false);
/* Set only works on existing cases. */
ok1(jmap_set(map, idx[0], 0) == false);
ok1(jmap_add(map, idx[0], 1) == true);
ok1(jmap_get(map, idx[0]) == 1);
ok1(jmap_set(map, idx[0], -1) == true);
ok1(jmap_get(map, idx[0]) == -1);
ok1(jmap_test(map, idx[0]) == true);
ok1(jmap_count(map) == 1);
ok1(jmap_first(map) == idx[0]);
ok1(jmap_next(map, idx[0]) == NULL);
ok1(jmap_del(map, idx[0]) == true);
ok1(jmap_test(map, idx[0]) == false);
ok1(jmap_count(map) == 0);
for (i = 0; i < NUM; i++)
jmap_add(map, idx[i], i+1);
ok1(jmap_count(map) == NUM);
ok1(jmap_first(map) == idx[0]);
ok1(jmap_next(map, idx[0]) == idx[1]);
ok1(jmap_next(map, idx[NUM-1]) == NULL);
ok1(jmap_get(map, idx[0]) == 1);
ok1(jmap_get(map, idx[NUM-1]) == NUM);
ok1(jmap_get(map, (void *)((char *)idx[NUM-1] + 1)) == 0);
/* Reverse values in map. */
for (i = 0; i < NUM; i++) {
intp = jmap_getval(map, idx[i]);
ok1(*intp == i+1);
*intp = NUM-i;
jmap_putval(map, &intp);
}
for (i = 0; i < NUM; i++)
ok1(jmap_get(map, idx[i]) == NUM-i);
intp = jmap_firstval(map, &index);
ok1(index == idx[0]);
ok1(*intp == NUM);
jmap_putval(map, &intp);
intp = jmap_nextval(map, &index);
ok1(index == idx[1]);
ok1(*intp == NUM-1);
jmap_putval(map, &intp);
index = idx[NUM-1];
intp = jmap_nextval(map, &index);
ok1(intp == NULL);
ok1(jmap_error(map) == NULL);
jmap_free(map);
for (i = 0; i < NUM+1; i++)
free(idx[i]);
return exit_status();
}
#include <ccan/tap/tap.h>
#include <ccan/jmap/jmap_type.h>
#include <ccan/jmap/jmap.c>
struct foo;
struct idx;
JMAP_DEFINE_PTRIDX_TYPE(struct idx, struct foo, foo);
struct jmap_foo {
JMAP_MEMBERS(struct idx *, struct foo *);
};
#define NUM 100
......@@ -32,70 +33,70 @@ int main(int argc, char *argv[])
for (i = 0; i < NUM+1; i++)
idx[i] = (void *)((char *)foo[i] + 1);
map = jmap_foo_new();
ok1(jmap_foo_error(map) == NULL);
map = jmap_new(struct jmap_foo);
ok1(jmap_error(map) == NULL);
ok1(jmap_foo_test(map, idx[NUM]) == false);
ok1(jmap_foo_get(map, idx[NUM]) == (struct foo *)NULL);
ok1(jmap_foo_count(map) == 0);
ok1(jmap_foo_first(map) == (struct idx *)NULL);
ok1(jmap_foo_del(map, idx[0]) == false);
ok1(jmap_test(map, idx[NUM]) == false);
ok1(jmap_get(map, idx[NUM]) == (struct foo *)NULL);
ok1(jmap_count(map) == 0);
ok1(jmap_first(map) == (struct idx *)NULL);
ok1(jmap_del(map, idx[0]) == false);
/* Set only works on existing cases. */
ok1(jmap_foo_set(map, idx[0], foo[0]) == false);
ok1(jmap_foo_add(map, idx[0], foo[1]) == true);
ok1(jmap_foo_get(map, idx[0]) == foo[1]);
ok1(jmap_foo_set(map, idx[0], foo[0]) == true);
ok1(jmap_foo_get(map, idx[0]) == foo[0]);
ok1(jmap_set(map, idx[0], foo[0]) == false);
ok1(jmap_add(map, idx[0], foo[1]) == true);
ok1(jmap_get(map, idx[0]) == foo[1]);
ok1(jmap_set(map, idx[0], foo[0]) == true);
ok1(jmap_get(map, idx[0]) == foo[0]);
ok1(jmap_foo_test(map, idx[0]) == true);
ok1(jmap_foo_count(map) == 1);
ok1(jmap_foo_first(map) == idx[0]);
ok1(jmap_foo_next(map, idx[0]) == NULL);
ok1(jmap_test(map, idx[0]) == true);
ok1(jmap_count(map) == 1);
ok1(jmap_first(map) == idx[0]);
ok1(jmap_next(map, idx[0]) == NULL);
ok1(jmap_foo_del(map, idx[0]) == true);
ok1(jmap_foo_test(map, idx[0]) == false);
ok1(jmap_foo_count(map) == 0);
ok1(jmap_del(map, idx[0]) == true);
ok1(jmap_test(map, idx[0]) == false);
ok1(jmap_count(map) == 0);
for (i = 0; i < NUM; i++)
jmap_foo_add(map, idx[i], foo[i]);
jmap_add(map, idx[i], foo[i]);
ok1(jmap_foo_count(map) == NUM);
ok1(jmap_count(map) == NUM);
ok1(jmap_foo_first(map) == idx[0]);
ok1(jmap_foo_next(map, idx[0]) == idx[1]);
ok1(jmap_foo_next(map, idx[NUM-1]) == NULL);
ok1(jmap_first(map) == idx[0]);
ok1(jmap_next(map, idx[0]) == idx[1]);
ok1(jmap_next(map, idx[NUM-1]) == NULL);
ok1(jmap_foo_get(map, idx[0]) == foo[0]);
ok1(jmap_foo_get(map, idx[NUM-1]) == foo[NUM-1]);
ok1(jmap_foo_get(map, (void *)((char *)idx[NUM-1] + 1)) == NULL);
ok1(jmap_get(map, idx[0]) == foo[0]);
ok1(jmap_get(map, idx[NUM-1]) == foo[NUM-1]);
ok1(jmap_get(map, (void *)((char *)idx[NUM-1] + 1)) == NULL);
/* Reverse values in map. */
for (i = 0; i < NUM; i++) {
foop = jmap_foo_getval(map, idx[i]);
foop = jmap_getval(map, idx[i]);
ok1(*foop == foo[i]);
*foop = foo[NUM-1-i];
jmap_foo_putval(map, &foop);
jmap_putval(map, &foop);
}
for (i = 0; i < NUM; i++)
ok1(jmap_foo_get(map, idx[i]) == foo[NUM-1-i]);
ok1(jmap_get(map, idx[i]) == foo[NUM-1-i]);
foop = jmap_foo_firstval(map, &index);
foop = jmap_firstval(map, &index);
ok1(index == idx[0]);
ok1(*foop == foo[NUM-1]);
jmap_foo_putval(map, &foop);
jmap_putval(map, &foop);
foop = jmap_foo_nextval(map, &index);
foop = jmap_nextval(map, &index);
ok1(index == idx[1]);
ok1(*foop == foo[NUM-2]);
jmap_foo_putval(map, &foop);
jmap_putval(map, &foop);
index = idx[NUM-1];
foop = jmap_foo_nextval(map, &index);
foop = jmap_nextval(map, &index);
ok1(foop == NULL);
ok1(jmap_foo_error(map) == NULL);
jmap_foo_free(map);
ok1(jmap_error(map) == NULL);
jmap_free(map);
for (i = 0; i < NUM+1; i++)
free(foo[i]);
......
#include <ccan/tap/tap.h>
#include <ccan/jmap/jmap_type.h>
#include <ccan/jmap/jmap.c>
struct foo;
JMAP_DEFINE_UINTIDX_TYPE(struct foo, foo);
struct jmap_foo {
JMAP_MEMBERS(unsigned long, struct foo *);
};
#define NUM 100
......@@ -14,117 +15,120 @@ int main(int argc, char *argv[])
struct foo *foo[NUM], **foop;
unsigned long i;
plan_tests(37 + NUM*2 + 19);
plan_tests(40 + NUM*2 + 19);
for (i = 0; i < NUM; i++)
foo[i] = malloc(20);
map = jmap_foo_new();
ok1(jmap_foo_error(map) == NULL);
map = jmap_new(struct jmap_foo);
ok1(jmap_error(map) == NULL);
ok1(jmap_foo_test(map, 0) == false);
ok1(jmap_foo_get(map, 0) == (struct foo *)NULL);
ok1(jmap_foo_popcount(map, 0, -1) == 0);
ok1(jmap_foo_first(map, 0) == 0);
ok1(jmap_foo_last(map, 0) == 0);
ok1(jmap_foo_del(map, 0) == false);
ok1(jmap_test(map, 0) == false);
ok1(jmap_get(map, 0) == (struct foo *)NULL);
ok1(jmap_popcount(map, 0, -1) == 0);
ok1(jmap_first(map) == 0);
ok1(jmap_last(map) == 0);
ok1(jmap_del(map, 0) == false);
/* Set only works on existing cases. */
ok1(jmap_foo_set(map, 0, foo[0]) == false);
ok1(jmap_foo_add(map, 0, foo[1]) == true);
ok1(jmap_foo_get(map, 0) == foo[1]);
ok1(jmap_foo_set(map, 0, foo[0]) == true);
ok1(jmap_foo_get(map, 0) == foo[0]);
ok1(jmap_foo_test(map, 0) == true);
ok1(jmap_foo_popcount(map, 0, -1) == 1);
ok1(jmap_foo_first(map, -1) == 0);
ok1(jmap_foo_last(map, -1) == 0);
ok1(jmap_foo_next(map, 0, -1) == (size_t)-1);
ok1(jmap_foo_prev(map, 0, -1) == (size_t)-1);
ok1(jmap_foo_del(map, 0) == true);
ok1(jmap_foo_test(map, 0) == false);
ok1(jmap_foo_popcount(map, 0, -1) == 0);
ok1(jmap_set(map, 1, foo[0]) == false);
ok1(jmap_add(map, 1, foo[1]) == true);
ok1(jmap_get(map, 1) == foo[1]);
ok1(jmap_set(map, 1, foo[0]) == true);
ok1(jmap_get(map, 1) == foo[0]);
ok1(jmap_test(map, 1) == true);
ok1(jmap_popcount(map, 0, -1) == 1);
ok1(jmap_first(map) == 1);
ok1(jmap_last(map) == 1);
ok1(jmap_next(map, 0) == 1);
ok1(jmap_next(map, 1) == 0);
ok1(jmap_prev(map, 2) == 1);
ok1(jmap_prev(map, 1) == 0);
ok1(jmap_del(map, 1) == true);
ok1(jmap_test(map, 1) == false);
ok1(jmap_popcount(map, 0, -1) == 0);
for (i = 0; i < NUM; i++)
jmap_foo_add(map, i, foo[i]);
ok1(jmap_foo_popcount(map, 0, -1) == NUM);
ok1(jmap_foo_popcount(map, 0, NUM-1) == NUM);
ok1(jmap_foo_popcount(map, 0, NUM/2-1) == NUM/2);
ok1(jmap_foo_popcount(map, NUM/2, NUM) == NUM - NUM/2);
ok1(jmap_foo_nth(map, 0, -1) == 0);
ok1(jmap_foo_nth(map, NUM-1, -1) == NUM-1);
ok1(jmap_foo_nth(map, NUM, -1) == (size_t)-1);
ok1(jmap_foo_first(map, -1) == 0);
ok1(jmap_foo_last(map, -1) == NUM-1);
ok1(jmap_foo_next(map, 0, -1) == 1);
ok1(jmap_foo_next(map, NUM-1, -1) == (size_t)-1);
ok1(jmap_foo_prev(map, 1, -1) == 0);
ok1(jmap_foo_prev(map, 0, -1) == (size_t)-1);
ok1(jmap_foo_get(map, 0) == foo[0]);
ok1(jmap_foo_get(map, NUM-1) == foo[NUM-1]);
ok1(jmap_foo_get(map, NUM) == NULL);
jmap_add(map, i+1, foo[i]);
ok1(jmap_count(map) == NUM);
ok1(jmap_popcount(map, 0, -1) == NUM);
ok1(jmap_popcount(map, 1, NUM) == NUM);
ok1(jmap_popcount(map, 1, NUM/2) == NUM/2);
ok1(jmap_popcount(map, NUM/2+1, NUM) == NUM - NUM/2);
ok1(jmap_nth(map, 0, -1) == 1);
ok1(jmap_nth(map, NUM-1, -1) == NUM);
ok1(jmap_nth(map, NUM, -1) == (size_t)-1);
ok1(jmap_first(map) == 1);
ok1(jmap_last(map) == NUM);
ok1(jmap_next(map, 1) == 2);
ok1(jmap_next(map, NUM) == 0);
ok1(jmap_prev(map, 2) == 1);
ok1(jmap_prev(map, 1) == 0);
ok1(jmap_get(map, 1) == foo[0]);
ok1(jmap_get(map, NUM) == foo[NUM-1]);
ok1(jmap_get(map, NUM+1) == NULL);
/* Reverse values in map. */
for (i = 0; i < NUM; i++) {
foop = jmap_foo_getval(map, i);
foop = jmap_getval(map, i+1);
ok1(*foop == foo[i]);
*foop = foo[NUM-1-i];
jmap_foo_putval(map, &foop);
jmap_putval(map, &foop);
}
for (i = 0; i < NUM; i++)
ok1(jmap_foo_get(map, i) == foo[NUM-1-i]);
ok1(jmap_get(map, i+1) == foo[NUM-1-i]);
foop = jmap_foo_nthval(map, 0, &i);
ok1(i == 0);
foop = jmap_nthval(map, 0, &i);
ok1(i == 1);
ok1(*foop == foo[NUM-1]);
jmap_foo_putval(map, &foop);
foop = jmap_foo_nthval(map, NUM-1, &i);
ok1(i == NUM-1);
jmap_putval(map, &foop);
foop = jmap_nthval(map, NUM-1, &i);
ok1(i == NUM);
ok1(*foop == foo[0]);
jmap_foo_putval(map, &foop);
jmap_putval(map, &foop);
foop = jmap_foo_firstval(map, &i);
ok1(i == 0);
foop = jmap_firstval(map, &i);
ok1(i == 1);
ok1(*foop == foo[NUM-1]);
jmap_foo_putval(map, &foop);
jmap_putval(map, &foop);
foop = jmap_foo_nextval(map, &i);
ok1(i == 1);
foop = jmap_nextval(map, &i);
ok1(i == 2);
ok1(*foop == foo[NUM-2]);
jmap_foo_putval(map, &foop);
jmap_putval(map, &foop);
foop = jmap_foo_prevval(map, &i);
ok1(i == 0);
foop = jmap_prevval(map, &i);
ok1(i == 1);
ok1(*foop == foo[NUM-1]);
jmap_foo_putval(map, &foop);
jmap_putval(map, &foop);
foop = jmap_foo_prevval(map, &i);
foop = jmap_prevval(map, &i);
ok1(foop == NULL);
foop = jmap_foo_lastval(map, &i);
ok1(i == NUM-1);
foop = jmap_lastval(map, &i);
ok1(i == NUM);
ok1(*foop == foo[0]);
jmap_foo_putval(map, &foop);
jmap_putval(map, &foop);
foop = jmap_foo_prevval(map, &i);
ok1(i == NUM-2);
foop = jmap_prevval(map, &i);
ok1(i == NUM-1);
ok1(*foop == foo[1]);
jmap_foo_putval(map, &foop);
jmap_putval(map, &foop);
foop = jmap_foo_nextval(map, &i);
ok1(i == NUM-1);
foop = jmap_nextval(map, &i);
ok1(i == NUM);
ok1(*foop == foo[0]);
jmap_foo_putval(map, &foop);
jmap_putval(map, &foop);
foop = jmap_foo_nextval(map, &i);
foop = jmap_nextval(map, &i);
ok1(foop == NULL);
ok1(jmap_foo_error(map) == NULL);
jmap_foo_free(map);
ok1(jmap_error(map) == NULL);
jmap_free(map);
for (i = 0; i < NUM; i++)
free(foo[i]);
......
......@@ -2,111 +2,113 @@
#define CCAN_JMAP_DEBUG
#include <ccan/jmap/jmap.c>
struct map {
JMAP_MEMBERS(unsigned long, unsigned long);
};
int main(int argc, char *argv[])
{
struct jmap *map;
struct map *map;
unsigned long i, *value;
const char *err;
plan_tests(53);
plan_tests(51);
map = jmap_new();
map = jmap_new(struct map);
ok1(jmap_error(map) == NULL);
ok1(jmap_test(map, 0) == false);
ok1(jmap_del(map, 0) == false);
ok1(jmap_add(map, 0, 1) == true);
ok1(jmap_test(map, 0) == true);
ok1(jmap_get(map, 0, -1) == 1);
ok1(jmap_get(map, 1, -1) == (size_t)-1);
ok1(jmap_get(map, 0) == 1);
ok1(jmap_get(map, 1) == 0);
ok1(jmap_del(map, 0) == true);
ok1(jmap_popcount(map, 0, -1) == 0);
ok1(jmap_nth(map, 0, 0) == 0);
ok1(jmap_nth(map, 0, -1) == (size_t)-1);
ok1(jmap_first(map, 0) == 0);
ok1(jmap_first(map, -1) == (size_t)-1);
ok1(jmap_last(map, 0) == 0);
ok1(jmap_last(map, -1) == (size_t)-1);
ok1(jmap_first(map) == 0);
ok1(jmap_last(map) == 0);
ok1(jmap_getval(map, 0) == NULL);
/* Map a million indices, 16 apart. */
for (i = 0; i < 1000000; i++)
jmap_add(map, i << 4, (i << 5) + 1);
jmap_add(map, (i << 4) + 1, (i << 5) + 1);
/* This only take 6.3MB on my 32-bit system. */
diag("%u bytes memory used\n", (unsigned)JudyLMemUsed(map->judy));
diag("%u bytes memory used\n", (unsigned)JudyLMemUsed(map->raw.judy));
ok1(jmap_get(map, 0, -1) == 1);
ok1(jmap_get(map, 999999 << 4, -1) == (999999 << 5) + 1);
ok1(jmap_get(map, 1) == 1);
ok1(jmap_get(map, (999999 << 4) + 1) == (999999 << 5) + 1);
ok1(jmap_popcount(map, 0, -1) == 1000000);
ok1(jmap_nth(map, 0, -1) == 0);
ok1(jmap_nth(map, 999999, -1) == 999999 << 4);
ok1(jmap_nth(map, 0, -1) == 1);
ok1(jmap_nth(map, 999999, -1) == (999999 << 4) + 1);
ok1(jmap_nth(map, 1000000, -1) == (size_t)-1);
ok1(jmap_first(map, -1) == 0);
ok1(jmap_last(map, -1) == 999999 << 4);
ok1(jmap_next(map, 0, -1) == 1 << 4);
ok1(jmap_next(map, 999999 << 4, -1) == (size_t)-1);
ok1(jmap_prev(map, 1, -1) == 0);
ok1(jmap_prev(map, 0, -1) == (size_t)-1);
ok1(jmap_first(map) == 1);
ok1(jmap_last(map) == (999999 << 4) + 1);
ok1(jmap_next(map, 1) == (1 << 4) + 1);
ok1(jmap_next(map, (999999 << 4) + 1) == 0);
ok1(jmap_prev(map, 2) == 1);
ok1(jmap_prev(map, 0) == 0);
ok1(jmap_error(map) == NULL);
/* Accessors. */
value = jmap_getval(map, 0);
value = jmap_getval(map, 1);
ok1(value && *value == 1);
*value = 2;
ok1(jmap_get(map, 0, -1) == 2);
ok1(jmap_get(map, 1) == 2);
jmap_putval(map, &value);
ok1(jmap_get(map, 0, -1) == 2);
ok1(jmap_set(map, 0, 1));
ok1(jmap_get(map, 1) == 2);
ok1(jmap_set(map, 1, 1));
value = jmap_getval(map, 999999 << 4);
value = jmap_getval(map, (999999 << 4) + 1);
ok1(value && *value == (999999 << 5) + 1);
jmap_putval(map, &value);
value = jmap_nthval(map, 0, &i);
ok1(i == 0);
ok1(i == 1);
ok1(value && *value == 1);
jmap_putval(map, &value);
value = jmap_nthval(map, 999999, &i);
ok1(i == 999999 << 4);
ok1(i == (999999 << 4) + 1);
ok1(value && *value == (999999 << 5) + 1);
jmap_putval(map, &value);
ok1(jmap_nthval(map, 1000000, &i) == NULL);
value = jmap_firstval(map, &i);
ok1(i == 0);
ok1(i == 1);
ok1(value && *value == 1);
jmap_putval(map, &value);
ok1(jmap_prevval(map, &i) == NULL);
i = 0;
i = 1;
value = jmap_nextval(map, &i);
ok1(i == 1 << 4);
ok1(i == (1 << 4) + 1);
ok1(value && *value == (1 << 5) + 1);
jmap_putval(map, &value);
value = jmap_lastval(map, &i);
ok1(i == 999999 << 4);
ok1(i == (999999 << 4) + 1);
ok1(value && *value == (999999 << 5) + 1);
jmap_putval(map, &value);
ok1(jmap_nextval(map, &i) == NULL);
i = 999999 << 4;
i = (999999 << 4) + 1;
value = jmap_prevval(map, &i);
ok1(i == 999998 << 4);
ok1(i == (999998 << 4) + 1);
ok1(value && *value == (999998 << 5) + 1);
jmap_putval(map, &value);
/* Test error handling */
JU_ERRNO(&map->err) = 100;
JU_ERRID(&map->err) = 991;
JU_ERRNO(&map->raw.err) = 100;
JU_ERRID(&map->raw.err) = 991;
err = jmap_error(map);
ok1(err);
ok1(strstr(err, "100"));
ok1(strstr(err, "991"));
ok1(err == map->errstr);
ok1(err == map->raw.errstr);
jmap_free(map);
return exit_status();
......
......@@ -74,8 +74,10 @@
*/
#if HAVE_TYPEOF
#define tcon_cast(x, canary, expr) ((__typeof__((x)->_tcon[0].canary))(expr))
#define tcon_cast_ptr(x, canary, expr) ((__typeof__(&(x)->_tcon[0].canary))(expr))
#else
#define tcon_cast(x, canary, expr) ((void *)(expr))
#define tcon_cast_ptr(x, canary, expr) ((void *)(expr))
#endif
#endif /* CCAN_TCON_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment