The usual way of construction strmap objects is to use the STRMAP_MEMBERS()
macro which expands to both a raw strmap structure and a tcon type canary.
However, the tcon type canary involves a flexible array member which means
that in standard C99 STRMAP_MEMBERS() must appear only at the end of a
structure definition. But worse, that structure can then only appear at
the end of any other structure it is included in, which is pretty
inconvenient for the intended purpose of creating type specific strmaps.
gcc extensions allow this to work (somehow), but clang complains loudly
about it.
The tcon module already includes the TCON_WRAP() mechanism, which already
provides this same sort of type-specific definitions in a more general way.
So convert strmap (and its users) to that approach.
This removes STRMAP_MEMBERS() entirely, breaking compatibility. I'm hoping
strmap is used in few enough places that we can get away with that.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
enum cdump_type_kind kind,
const char *name)
{
enum cdump_type_kind kind,
const char *name)
{
struct cdump_type *t;
switch (kind) {
struct cdump_type *t;
switch (kind) {
static bool gather_undefines(const char *name,
struct cdump_type *t,
static bool gather_undefines(const char *name,
struct cdump_type *t,
- struct cdump_map *undefs)
{
if (!type_defined(t))
strmap_add(undefs, name, t);
{
if (!type_defined(t))
strmap_add(undefs, name, t);
static bool remove_from_map(const char *name,
struct cdump_type *t,
static bool remove_from_map(const char *name,
struct cdump_type *t,
{
strmap_del(map, name, NULL);
return true;
}
{
strmap_del(map, name, NULL);
return true;
}
-static void remove_undefined(struct cdump_map *map)
+static void remove_undefined(cdump_map_t *map)
- struct cdump_map undefs;
/* We can't delete inside iterator, so gather all the undefs
* then remove them. */
/* We can't delete inside iterator, so gather all the undefs
* then remove them. */
};
/* The map of typenames to definitions */
};
/* The map of typenames to definitions */
-struct cdump_map {
- STRMAP_MEMBERS(struct cdump_type *);
-};
+typedef STRMAP(struct cdump_type *) cdump_map_t;
struct cdump_definitions {
struct cdump_definitions {
- struct cdump_map enums;
- struct cdump_map structs;
- struct cdump_map unions;
+ cdump_map_t enums;
+ cdump_map_t structs;
+ cdump_map_t unions;
* int main(int argc, char *argv[])
* {
* size_t i;
* int main(int argc, char *argv[])
* {
* size_t i;
- * struct { STRMAP_MEMBERS(size_t); } map;
*
* strmap_init(&map);
* for (i = 1; i < argc; i++)
*
* strmap_init(&map);
* for (i = 1; i < argc; i++)
- * STRMAP_MEMBERS - declare members for a type-specific strmap.
+ * STRMAP - declare a type-specific strmap
* @type: type for this map's values, or void * for any pointer.
*
* You use this to create your own typed strmap for a particular type.
* @type: type for this map's values, or void * for any pointer.
*
* You use this to create your own typed strmap for a particular type.
- * struct strmap_intp {
- * STRMAP_MEMBERS(int *);
- * };
+ * STRMAP(int *) int_strmap;
+ * strmap_init(&int_strmap);
-#define STRMAP_MEMBERS(type) \
- struct strmap raw; \
- TCON(type canary)
-
+#define STRMAP(type) \
+ TCON_WRAP(struct strmap, type canary)
/**
* strmap_init - initialize a string map (empty)
/**
* strmap_init - initialize a string map (empty)
* need this.
*
* Example:
* need this.
*
* Example:
- * struct strmap_intp map;
*
* strmap_init(&map);
*/
*
* strmap_init(&map);
*/
-#define strmap_init(map) strmap_init_(&(map)->raw)
+#define strmap_init(map) strmap_init_(tcon_unwrap(map))
static inline void strmap_init_(struct strmap *map)
{
static inline void strmap_init_(struct strmap *map)
{
* if (!strmap_empty(&map))
* abort();
*/
* if (!strmap_empty(&map))
* abort();
*/
-#define strmap_empty(map) strmap_empty_(&(map)->raw)
+#define strmap_empty(map) strmap_empty_(tcon_unwrap(map))
static inline bool strmap_empty_(const struct strmap *map)
{
static inline bool strmap_empty_(const struct strmap *map)
{
* printf("hello => %i\n", *val);
*/
#define strmap_get(map, member) \
* printf("hello => %i\n", *val);
*/
#define strmap_get(map, member) \
- tcon_cast((map), canary, strmap_get_(&(map)->raw, (member)))
+ tcon_cast((map), canary, strmap_get_(tcon_unwrap(map), (member)))
void *strmap_get_(const struct strmap *map, const char *member);
/**
void *strmap_get_(const struct strmap *map, const char *member);
/**
* if (!strmap_add(&map, "goodbye", val))
* printf("goodbye was already in the map\n");
*/
* if (!strmap_add(&map, "goodbye", val))
* printf("goodbye was already in the map\n");
*/
-#define strmap_add(map, member, value) \
- strmap_add_(&tcon_check((map), canary, (value))->raw, \
+#define strmap_add(map, member, value) \
+ strmap_add_(tcon_unwrap(tcon_check((map), canary, (value))), \
(member), (void *)(value))
bool strmap_add_(struct strmap *map, const char *member, const void *value);
(member), (void *)(value))
bool strmap_add_(struct strmap *map, const char *member, const void *value);
* printf("goodbye was not in the map?\n");
*/
#define strmap_del(map, member, valuep) \
* printf("goodbye was not in the map?\n");
*/
#define strmap_del(map, member, valuep) \
- strmap_del_(&tcon_check_ptr((map), canary, valuep)->raw, \
+ strmap_del_(tcon_unwrap(tcon_check_ptr((map), canary, valuep)), \
(member), (void **)valuep)
char *strmap_del_(struct strmap *map, const char *member, void **valuep);
(member), (void **)valuep)
char *strmap_del_(struct strmap *map, const char *member, void **valuep);
* Example:
* strmap_clear(&map);
*/
* Example:
* strmap_clear(&map);
*/
-#define strmap_clear(map) strmap_clear_(&(map)->raw)
+#define strmap_clear(map) strmap_clear_(tcon_unwrap(map))
void strmap_clear_(struct strmap *map);
void strmap_clear_(struct strmap *map);
* You should not alter the map within the @handle function!
*
* Example:
* You should not alter the map within the @handle function!
*
* Example:
- * struct strmap_intp {
- * STRMAP_MEMBERS(int *);
- * };
+ * typedef STRMAP(int *) strmap_intp;
* static bool dump_some(const char *member, int *value, int *num)
* {
* // Only dump out num nodes.
* static bool dump_some(const char *member, int *value, int *num)
* {
* // Only dump out num nodes.
- * static void dump_map(const struct strmap_intp *map)
+ * static void dump_map(const strmap_intp *map)
* {
* int max = 100;
* strmap_iterate(map, dump_some, &max);
* {
* int max = 100;
* strmap_iterate(map, dump_some, &max);
* }
*/
#define strmap_iterate(map, handle, arg) \
* }
*/
#define strmap_iterate(map, handle, arg) \
- strmap_iterate_(&(map)->raw, \
+ strmap_iterate_(tcon_unwrap(map), \
typesafe_cb_cast(bool (*)(const char *, \
void *, void *), \
bool (*)(const char *, \
typesafe_cb_cast(bool (*)(const char *, \
void *, void *), \
bool (*)(const char *, \
* strmap_empty() on the returned pointer.
*
* Example:
* strmap_empty() on the returned pointer.
*
* Example:
- * static void dump_prefix(const struct strmap_intp *map,
+ * static void dump_prefix(const strmap_intp *map,
* const char *prefix)
* {
* int max = 100;
* const char *prefix)
* {
* int max = 100;
*/
#if HAVE_TYPEOF
#define strmap_prefix(map, prefix) \
*/
#if HAVE_TYPEOF
#define strmap_prefix(map, prefix) \
- ((const __typeof__(map))strmap_prefix_(&(map)->raw, (prefix)))
+ ((const __typeof__(map))strmap_prefix_(tcon_unwrap(map), (prefix)))
#else
#define strmap_prefix(map, prefix) \
#else
#define strmap_prefix(map, prefix) \
- ((const void *)strmap_prefix_(&(map)->raw, (prefix)))
+ ((const void *)strmap_prefix_(tcon_unwrap(map), (prefix)))
#endif
const struct strmap *strmap_prefix_(const struct strmap *map,
#endif
const struct strmap *strmap_prefix_(const struct strmap *map,
- struct strmap_charp {
- STRMAP_MEMBERS(char *);
- } map;
- struct strmap_charp {
- STRMAP_MEMBERS(char *);
- } map;
unsigned int i;
char *str[NUM];
bool dump_ok;
unsigned int i;
char *str[NUM];
bool dump_ok;
- struct map {
- STRMAP_MEMBERS(char *);
- };
- struct map map;
- const struct map *sub;
+ typedef STRMAP(char *) map_t;
+ map_t map;
+ const map_t *sub;
unsigned int i;
char *str[NUM], *empty;
unsigned int i;
char *str[NUM], *empty;
/* Everything */
sub = strmap_prefix(&map, "0");
/* Everything */
sub = strmap_prefix(&map, "0");
- ok1(sub->raw.u.n == map.raw.u.n);
+ ok1(tcon_unwrap(sub)->u.n == tcon_unwrap(&map)->u.n);
sub = strmap_prefix(&map, "");
sub = strmap_prefix(&map, "");
- ok1(sub->raw.u.n == map.raw.u.n);
+ ok1(tcon_unwrap(sub)->u.n == tcon_unwrap(&map)->u.n);
/* Single. */
sub = strmap_prefix(&map, "00000000");
/* Single. */
sub = strmap_prefix(&map, "00000000");
- struct strmap_charp {
- STRMAP_MEMBERS(char *);
- } map;
const char str[] = "hello";
const char val[] = "there";
const char none[] = "";
const char str[] = "hello";
const char val[] = "there";
const char none[] = "";
#include <ccan/tal/path/path.h>
#include <ccan/strmap/strmap.h>
#include <ccan/tal/path/path.h>
#include <ccan/strmap/strmap.h>
-struct ccanlint_map {
- STRMAP_MEMBERS(struct ccanlint *);
-};
+typedef STRMAP(struct ccanlint *) ccanlint_map_t;
-static struct ccanlint_map tests;
+static ccanlint_map_t tests;
bool safe_mode = false;
bool keep_results = false;
bool non_ccan_deps = false;
bool safe_mode = false;
bool keep_results = false;
bool non_ccan_deps = false;
}
static bool check_names(const char *member, struct ccanlint *c,
}
static bool check_names(const char *member, struct ccanlint *c,
- struct ccanlint_map *names)
{
if (!strmap_add(names, c->name, c))
err(1, "Duplicate name %s", c->name);
{
if (!strmap_add(names, c->name, c))
err(1, "Duplicate name %s", c->name);
static void init_tests(void)
{
static void init_tests(void)
{
- struct ccanlint_map names;
struct ccanlint **table;
size_t i, num;
struct ccanlint **table;
size_t i, num;