return intmap_first_(&prev->u.n->child[1], indexp);
}
+void *intmap_last_(const struct intmap *map, intmap_index_t *indexp)
+{
+ const struct intmap *n;
+
+ if (intmap_empty_(map)) {
+ errno = ENOENT;
+ return NULL;
+ }
+
+ n = map;
+ /* Anything with NULL value is a node. */
+ while (!n->v)
+ n = &n->u.n->child[1];
+ errno = 0;
+ *indexp = n->u.i;
+ return n->v;
+}
+
static void clear(struct intmap n)
{
if (!n.v) {
tcon_cast((smap), sintmap_canary, \
sintmap_after_(sintmap_unwrap_(smap), (indexp)))
+/**
+ * uintmap_last - get last value in an unsigned intmap
+ * @umap: the typed intmap to iterate through.
+ * @indexp: a pointer to store the index.
+ *
+ * Returns NULL if the map is empty, otherwise populates *@indexp and
+ * returns the highest entry.
+ */
+#define uintmap_last(umap, indexp) \
+ tcon_cast((umap), uintmap_canary, \
+ intmap_last_(uintmap_unwrap_(umap), (indexp)))
+
+void *intmap_last_(const struct intmap *map, intmap_index_t *indexp);
+
+/**
+ * sintmap_last - get last value in a signed intmap
+ * @smap: the typed intmap to iterate through.
+ * @indexp: a pointer to store the index.
+ *
+ * Returns NULL if the map is empty, otherwise populates *@indexp and
+ * returns the highest entry.
+ */
+#define sintmap_last(smap, indexp) \
+ tcon_cast((smap), sintmap_canary, \
+ sintmap_last_(sintmap_unwrap_(smap), (indexp)))
+
/* TODO: We could implement intmap_prefix. */
/* These make sure it really is a uintmap/sintmap */
*indexp = SINTMAP_UNOFF(i);
return ret;
}
+
+static inline void *sintmap_last_(const struct intmap *map,
+ sintmap_index_t *indexp)
+{
+ intmap_index_t i;
+ void *ret = intmap_last_(map, &i);
+ *indexp = SINTMAP_UNOFF(i);
+ return ret;
+
+}
#endif /* CCAN_INTMAP_H */
{
/* This is a larger type than unsigned, and allows negative */
int64_t prev;
- intmap_index_t i;
+ intmap_index_t i, last_idx;
uint8_t *v;
+ bool last = true;
/* Must be in order, must contain value. */
prev = -1;
if (*v != i)
return false;
prev = i;
+ last = (uintmap_last(map, &last_idx) == v);
}
- return true;
+ return last;
}
static bool check_smap(const smap *map)
{
/* This is a larger type than int, and allows negative */
int64_t prev;
- sintmap_index_t i;
+ sintmap_index_t i, last_idx;
int8_t *v;
+ bool last = true;
/* Must be in order, must contain value. */
prev = -0x80000001ULL;
if (*v != i)
return false;
prev = i;
+ last = (sintmap_last(map, &last_idx) == v);
}
- return true;
+ return last;
}
int main(void)
{
/* This is a larger type than unsigned, and allows negative */
int64_t prev;
- uint64_t i;
+ uint64_t i, last_idx;
unsigned int *v;
+ bool last = true;
/* Must be in order, must contain value. */
prev = -1;
if (*v != i)
return false;
prev = i;
+ last = (uintmap_last(map, &last_idx) == v);
}
- return true;
+ return last;
}
static bool check_smap(const smap *map)
{
/* This is a larger type than int, and allows negative */
- int64_t prev, i;
+ int64_t prev, i, last_idx;
int *v;
+ bool last = true;
/* Must be in order, must contain value. */
prev = -0x80000001ULL;
return false;
if (*v != i)
return false;
+ last = (sintmap_last(map, &last_idx) == v);
prev = i;
}
- return true;
+ return last;
}
int main(void)
int64_t s;
/* This is how many tests you plan to run */
- plan_tests(35);
+ plan_tests(38);
sintmap_init(&map);
/* Test boundaries. */
ok1(!sintmap_get(&map, 0x7FFFFFFFFFFFFFFFLL));
ok1(!sintmap_get(&map, -0x8000000000000000LL));
ok1(sintmap_first(&map, &s) == NULL);
+ ok1(sintmap_last(&map, &s) == NULL);
ok1(errno == ENOENT);
s = 0x7FFFFFFFFFFFFFFFLL;
ok1(sintmap_after(&map, &s) == NULL);
ok1(sintmap_add(&map, 0x7FFFFFFFFFFFFFFFLL, first));
ok1(sintmap_get(&map, 0x7FFFFFFFFFFFFFFFLL) == first);
ok1(sintmap_first(&map, &s) == first && s == 0x7FFFFFFFFFFFFFFFLL);
+ ok1(sintmap_last(&map, &s) == first && s == 0x7FFFFFFFFFFFFFFFLL);
ok1(errno == 0);
ok1(sintmap_add(&map, -0x8000000000000000LL, second));
ok1(sintmap_get(&map, 0x7FFFFFFFFFFFFFFFLL) == first);
ok1(sintmap_get(&map, -0x8000000000000000LL) == second);
ok1(sintmap_first(&map, &s) == second && s == -0x8000000000000000LL);
ok1(sintmap_after(&map, &s) == first && s == 0x7FFFFFFFFFFFFFFFLL);
+ ok1(sintmap_last(&map, &s) == first && s == 0x7FFFFFFFFFFFFFFFLL);
ok1(errno == 0);
s = 0x7FFFFFFFFFFFFFFELL;
ok1(sintmap_after(&map, &s) == first && s == 0x7FFFFFFFFFFFFFFFLL);
UINTMAP(char *) map;
const char val[] = "there";
const char none[] = "";
+ uint64_t idx;
/* This is how many tests you plan to run */
- plan_tests(28);
+ plan_tests(40);
uintmap_init(&map);
ok1(errno == ENOENT);
ok1(!uintmap_del(&map, 0));
ok1(errno == ENOENT);
+ ok1(!uintmap_first(&map, &idx));
+ ok1(errno == ENOENT);
+ ok1(!uintmap_last(&map, &idx));
+ ok1(errno == ENOENT);
ok1(uintmap_add(&map, 1, val));
ok1(uintmap_get(&map, 1) == val);
ok1(!uintmap_get(&map, 0));
ok1(errno == ENOENT);
+ ok1(uintmap_first(&map, &idx) == val);
+ ok1(idx == 1);
+ ok1(uintmap_last(&map, &idx) == val);
+ ok1(idx == 1);
/* Add a duplicate should fail. */
ok1(!uintmap_add(&map, 1, val));
ok1(uintmap_add(&map, 1, val));
ok1(uintmap_get(&map, 1) == val);
ok1(uintmap_get(&map, 0) == none);
+ ok1(uintmap_first(&map, &idx) == none);
+ ok1(idx == 0);
+ ok1(uintmap_last(&map, &idx) == val);
+ ok1(idx == 1);
ok1(!uintmap_del(&map, 2));
ok1(uintmap_del(&map, 0) == none);
ok1(uintmap_get(&map, 1) == val);