1#!perl -w
2use ktemplate;
3# List of parameters accepted for substitution.
4@parms = qw(NAME KEY VALUE COMPARE COPYKEY FREEKEY FREEVALUE);
5# Defaults, if any.
6$parm{"COPYKEY"} = "0";
7$parm{"FREEKEY"} = "0";
8$parm{"FREEVALUE"} = "0";
9#
10&run;
11#
12__DATA__
13/*
14 * map, generated from template
15 * map name: <NAME>
16 * key: <KEY>
17 * value: <VALUE>
18 * compare: <COMPARE>
19 * copy_key: <COPYKEY>
20 * free_key: <FREEKEY>
21 * free_value: <FREEVALUE>
22 */
23struct <NAME>__element {
24    <KEY> key;
25    <VALUE> value;
26    struct <NAME>__element *next;
27};
28struct <NAME>__head {
29    struct <NAME>__element *first;
30};
31typedef struct <NAME>__head <NAME>;
32static inline int <NAME>_init (struct <NAME>__head *head)
33{
34    head->first = NULL;
35    return 0;
36}
37static inline void <NAME>_destroy (struct <NAME>__head *head)
38{
39    struct <NAME>__element *e, *e_next;
40    void (*free_key)(<KEY>) = <FREEKEY>;
41    void (*free_value)(<VALUE>) = <FREEVALUE>;
42    for (e = head->first; e; e = e_next) {
43	e_next = e->next;
44	if (free_key)
45	    (*free_key)(e->key);
46	if (free_value)
47	    (*free_value)(e->value);
48	free(e);
49    }
50    head->first = NULL;
51}
52/* Returns pointer to linked-list entry, or null if key not found.  */
53static inline struct <NAME>__element *
54<NAME>__find_node (struct <NAME>__head *head, <KEY> key)
55{
56    struct <NAME>__element *e;
57    for (e = head->first; e; e = e->next)
58	if (<COMPARE> (key, e->key) == 0)
59	    return e;
60    return 0;
61}
62/* Returns pointer to value, or null if key not found.  */
63static inline <VALUE> *
64<NAME>_find (struct <NAME>__head *head, <KEY> key)
65{
66    struct <NAME>__element *e = <NAME>__find_node(head, key);
67    if (e)
68	return &e->value;
69    return 0;
70}
71/* Returns 0 or error code.  */
72static inline int
73<NAME>__copy_key (<KEY> *out, <KEY> in)
74{
75    int (*copykey)(<KEY> *, <KEY>) = <COPYKEY>;
76    if (copykey == 0) {
77	*out = in;
78	return 0;
79    } else
80	return (*copykey)(out, in);
81}
82/* Returns 0 or error code.  */
83static inline int
84<NAME>_replace_or_insert (struct <NAME>__head *head,
85			  <KEY> key, <VALUE> new_value)
86{
87    struct <NAME>__element *e = <NAME>__find_node(head, key);
88    int ret;
89
90    if (e) {
91	/* replace */
92	void (*free_value)(<VALUE>) = <FREEVALUE>;
93	if (free_value)
94	    (*free_value)(e->value);
95	e->value = new_value;
96    } else {
97	/* insert */
98	e = malloc(sizeof(*e));
99	if (e == NULL)
100	    return ENOMEM;
101	ret = <NAME>__copy_key (&e->key, key);
102	if (ret) {
103	    free(e);
104	    return ret;
105	}
106	e->value = new_value;
107	e->next = head->first;
108	head->first = e;
109    }
110    return 0;
111}
112