]> git.ozlabs.org Git - ccan/blobdiff - ccan/intmap/intmap.h
intmap: implement intmap_before()
[ccan] / ccan / intmap / intmap.h
index 07a86351597dadb6f367b570ee132eab10733d33..834c969fa7c77e46dcc262b50b7b4c80b3c9b4d5 100644 (file)
@@ -286,7 +286,7 @@ void *intmap_first_(const struct intmap *map, intmap_index_t *indexp);
 /**
  * uintmap_after - get the closest following index in an unsigned intmap
  * @umap: the typed intmap to iterate through.
- * @indexp: the preceeding index (may not exist)
+ * @indexp: the preceding index (may not exist)
  *
  * Returns NULL if the there is no entry > @indexp, otherwise
  * populates *@indexp and returns the lowest entry > @indexp.
@@ -300,7 +300,7 @@ 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.
- * @indexp: the preceeding index (may not exist)
+ * @indexp: the preceding index (may not exist)
  *
  * Returns NULL if the there is no entry > @indexp, otherwise
  * populates *@indexp and returns the lowest entry > @indexp.
@@ -309,6 +309,32 @@ void *intmap_after_(const struct intmap *map, intmap_index_t *indexp);
        tcon_cast((smap), sintmap_canary,                               \
                  sintmap_after_(sintmap_unwrap_(smap), (indexp)))
 
+/**
+ * uintmap_before - get the closest preceding index in an unsigned intmap
+ * @umap: the typed intmap to iterate through.
+ * @indexp: the succeeding index (may not exist)
+ *
+ * Returns NULL if the there is no entry < @indexp, otherwise
+ * populates *@indexp and returns the highest entry < @indexp.
+ */
+#define uintmap_before(umap, indexp)                                   \
+       tcon_cast((umap), uintmap_canary,                               \
+                 intmap_before_(uintmap_unwrap_(umap), (indexp)))
+
+void *intmap_before_(const struct intmap *map, intmap_index_t *indexp);
+
+/**
+ * sintmap_before - get the closest preceding index in a signed intmap
+ * @smap: the typed intmap to iterate through.
+ * @indexp: the succeeding index (may not exist)
+ *
+ * Returns NULL if the there is no entry < @indexp, otherwise
+ * populates *@indexp and returns the highest entry < @indexp.
+ */
+#define sintmap_before(smap, indexp)                                   \
+       tcon_cast((smap), sintmap_canary,                               \
+                 sintmap_before_(sintmap_unwrap_(smap), (indexp)))
+
 /**
  * uintmap_last - get last value in an unsigned intmap
  * @umap: the typed intmap to iterate through.
@@ -335,6 +361,95 @@ void *intmap_last_(const struct intmap *map, intmap_index_t *indexp);
        tcon_cast((smap), sintmap_canary,                               \
                  sintmap_last_(sintmap_unwrap_(smap), (indexp)))
 
+/**
+ * uintmap_iterate - ordered iteration over an unsigned intmap
+ * @umap: the typed intmap to iterate through.
+ * @handle: the function to call.
+ * @arg: the argument for the function (types should match).
+ *
+ * @handle's prototype should be:
+ *     bool @handle(intmap_index_t index, type value, typeof(arg) arg)
+ *
+ * If @handle returns false, the iteration will stop and uintmap_iterate will
+ * return false, otherwise uintmap_iterate will return true.
+ * You should not alter the map within the @handle function!
+ *
+ * Example:
+ *     typedef UINTMAP(int *) umap_intp;
+ *     static bool dump_some(intmap_index_t index, int *value, int *num)
+ *     {
+ *             // Only dump out num nodes.
+ *             if (*(num--) == 0)
+ *                     return false;
+ *             printf("%lu=>%i\n", (unsigned long)index, *value);
+ *             return true;
+ *     }
+ *
+ *     static void dump_map(const umap_intp *map)
+ *     {
+ *             int max = 100;
+ *             uintmap_iterate(map, dump_some, &max);
+ *             if (max < 0)
+ *                     printf("... (truncated to 100 entries)\n");
+ *     }
+ */
+#define uintmap_iterate(map, handle, arg)                              \
+       intmap_iterate_(tcon_unwrap(map),                               \
+                       typesafe_cb_cast(bool (*)(intmap_index_t,       \
+                                                 void *, void *),      \
+                                        bool (*)(intmap_index_t,       \
+                                                 tcon_type((map),      \
+                                                           uintmap_canary), \
+                                                 __typeof__(arg)), (handle)), \
+                       (arg), 0)
+
+/**
+ * sintmap_iterate - ordered iteration over a signed intmap
+ * @smap: the typed intmap to iterate through.
+ * @handle: the function to call.
+ * @arg: the argument for the function (types should match).
+ *
+ * @handle's prototype should be:
+ *     bool @handle(sintmap_index_t index, type value, typeof(arg) arg)
+ *
+ * If @handle returns false, the iteration will stop and sintmap_iterate will
+ * return false, otherwise sintmap_iterate will return true.
+ * You should not alter the map within the @handle function!
+ *
+ * Example:
+ *     typedef SINTMAP(int *) smap_intp;
+ *     static bool dump_some(sintmap_index_t index, int *value, int *num)
+ *     {
+ *             // Only dump out num nodes.
+ *             if (*(num--) == 0)
+ *                     return false;
+ *             printf("%li=>%i\n", (long)index, *value);
+ *             return true;
+ *     }
+ *
+ *     static void dump_map(const smap_intp *map)
+ *     {
+ *             int max = 100;
+ *             sintmap_iterate(map, dump_some, &max);
+ *             if (max < 0)
+ *                     printf("... (truncated to 100 entries)\n");
+ *     }
+ */
+#define sintmap_iterate(map, handle, arg)                              \
+       intmap_iterate_(tcon_unwrap(map),                               \
+                       typesafe_cb_cast(bool (*)(intmap_index_t,       \
+                                                 void *, void *),      \
+                                        bool (*)(sintmap_index_t,      \
+                                                 tcon_type((map),      \
+                                                           sintmap_canary), \
+                                                 __typeof__(arg)), (handle)), \
+                       (arg), SINTMAP_OFFSET)
+
+bool intmap_iterate_(const struct intmap *map,
+                    bool (*handle)(intmap_index_t, void *, void *),
+                    void *data,
+                    intmap_index_t offset);
+
 /* TODO: We could implement intmap_prefix. */
 
 /* These make sure it really is a uintmap/sintmap */
@@ -366,6 +481,15 @@ static inline void *sintmap_after_(const struct intmap *map,
        return ret;
 }
 
+static inline void *sintmap_before_(const struct intmap *map,
+                                  sintmap_index_t *indexp)
+{
+       intmap_index_t i = SINTMAP_OFF(*indexp);
+       void *ret = intmap_before_(map, &i);
+       *indexp = SINTMAP_UNOFF(i);
+       return ret;
+}
+
 static inline void *sintmap_last_(const struct intmap *map,
                                  sintmap_index_t *indexp)
 {