]> git.ozlabs.org Git - ccan/blobdiff - ccan/intmap/intmap.h
intmap: clean up iterators.
[ccan] / ccan / intmap / intmap.h
index f06f02d0ee599c9045c496ba7ad979d83c8b0cf0..be3dbc0936b40f9133b4caad30b4a49c62c1bd42 100644 (file)
 /* Must be an unsigned type. */
 #ifndef intmap_index_t
 #define intmap_index_t uint64_t
+#define sintmap_index_t int64_t
 #endif
 
-/* Maximum possible values of each type */
-#define UINTMAP_NONE ((intmap_index_t)-1)
-#define SINTMAP_NONE (((intmap_index_t)1 << (sizeof(intmap_index_t)*8))-1)
-
 /**
  * struct intmap - representation of an integer map
  *
@@ -261,52 +258,58 @@ void *intmap_del_(struct intmap *map, intmap_index_t index);
 void intmap_clear_(struct intmap *map);
 
 /**
- * uintmap_first - get first index in an unsigned intmap
+ * uintmap_first - get first value in an unsigned intmap
  * @umap: the typed intmap to iterate through.
+ * @indexp: a pointer to store the index.
  *
- * Returns UINTMAP_NONE and sets errno to ENOENT if it's empty.
- * Otherwise errno is set to 0.
+ * Returns NULL if the map is empty, otherwise populates *@indexp and
+ * returns the lowest entry.
  */
-#define uintmap_first(umap)                    \
-       intmap_first_(uintmap_unwrap_(umap))
+#define uintmap_first(umap, indexp)                                    \
+       tcon_cast((umap), uintmap_canary,                               \
+                 intmap_first_(uintmap_unwrap_(umap), (indexp)))
+
+void *intmap_first_(const struct intmap *map, intmap_index_t *indexp);
 
 /**
- * sintmap_first - get first index in a signed intmap
+ * sintmap_first - get first value in a signed intmap
  * @smap: the typed intmap to iterate through.
+ * @indexp: a pointer to store the index.
  *
- * Returns SINTMAP_NONE and sets errno to ENOENT if it's
- * empty.  Otherwise errno is set to 0.
+ * Returns NULL if the map is empty, otherwise populates *@indexp and
+ * returns the lowest entry.
  */
-#define sintmap_first(smap)                                    \
-       SINTMAP_UNOFF(intmap_first_(sintmap_unwrap_(smap)))
-
-intmap_index_t intmap_first_(const struct intmap *map);
+#define sintmap_first(smap, indexp)                                    \
+       tcon_cast((smap), sintmap_canary,                               \
+                 sintmap_first_(sintmap_unwrap_(smap), (indexp)))
 
 /**
  * uintmap_after - get the closest following index in an unsigned intmap
  * @umap: the typed intmap to iterate through.
- * @i: the preceeding index (may not exist)
+ * @indexp: the preceeding index (may not exist)
  *
- * Returns UINTMAP_NONE and sets errno to ENOENT if there are no
- * others.  Otherwise errno is set to 0.
+ * Returns NULL if the there is no entry > @indexp, otherwise
+ * populates *@indexp and returns the lowest entry > @indexp.
  */
-#define uintmap_after(umap, i)                         \
-       intmap_after_(uintmap_unwrap_(umap), (i))
+#define uintmap_after(umap, indexp)                                    \
+       tcon_cast((umap), uintmap_canary,                               \
+                 intmap_after_(uintmap_unwrap_(umap), (indexp)))
+
+void *intmap_after_(const struct intmap *map, intmap_index_t *indexp);
 
 /**
  * sintmap_after - get the closest following index in a signed intmap
  * @smap: the typed intmap to iterate through.
- * @i: the preceeding index.
+ * @indexp: the preceeding index (may not exist)
  *
- * Returns SINTMAP_NONE and sets errno to ENOENT if there are no
- * others.  Otherwise errno is set to 0.
+ * Returns NULL if the there is no entry > @indexp, otherwise
+ * populates *@indexp and returns the lowest entry > @indexp.
  */
-#define sintmap_after(smap, i)                                         \
-       SINTMAP_UNOFF(intmap_after_(sintmap_unwrap_(smap), SINTMAP_OFF((i))))
-
-intmap_index_t intmap_after_(const struct intmap *map, intmap_index_t i);
+#define sintmap_after(smap, indexp)                                    \
+       tcon_cast((smap), sintmap_canary,                               \
+                 sintmap_after_(sintmap_unwrap_(smap), (indexp)))
 
-/* TODO: We could implement intmap_prefix, intmap_iterate... */
+/* TODO: We could implement intmap_prefix. */
 
 /* These make sure it really is a uintmap/sintmap */
 #define uintmap_unwrap_(u) (tcon_unwrap(u) + 0*tcon_sizeof((u), uintmap_canary))
@@ -317,4 +320,23 @@ intmap_index_t intmap_after_(const struct intmap *map, intmap_index_t i);
 #define SINTMAP_OFF(index)     ((intmap_index_t)(index) + SINTMAP_OFFSET)
 #define SINTMAP_UNOFF(index)   ((intmap_index_t)(index) - SINTMAP_OFFSET)
 
+/* Due to multi-evaluation, these can't be macros */
+static inline void *sintmap_first_(const struct intmap *map,
+                                  sintmap_index_t *indexp)
+{
+       intmap_index_t i;
+       void *ret = intmap_first_(map, &i);
+       *indexp = SINTMAP_UNOFF(i);
+       return ret;
+
+}
+
+static inline void *sintmap_after_(const struct intmap *map,
+                                  sintmap_index_t *indexp)
+{
+       intmap_index_t i = SINTMAP_OFF(*indexp);
+       void *ret = intmap_after_(map, &i);
+       *indexp = SINTMAP_UNOFF(i);
+       return ret;
+}
 #endif /* CCAN_INTMAP_H */