6962cb45fc033bfbca291a95782b90bab4e87626
[ccan] / ccan / tal / link / _info
1 #include "config.h"
2 #include <stdio.h>
3 #include <string.h>
4
5 /**
6  * tal/link - link helper for tal
7  *
8  * Tal does not support talloc-style references.  In the cases where
9  * an object needs multiple parents, all parents need to be aware of
10  * the situation; thus tal/link is a helper where all "parents"
11  * tal_link an object they agree to share ownership of.
12  *
13  * Example:
14  *      // Silly program which keeps a cache of uppercased strings.
15  *      // The cache wants to keep strings around even after they may have
16  *      // been "freed" by the caller.
17  *      // Given 'hello' outputs '1 cache hits HELLO '
18  *      // Given 'hello hello there' outputs '4 cache hits HELLO HELLO THERE '
19  *      #include <stdio.h>
20  *      #include <err.h>
21  *      #include <string.h>
22  *      #include <ctype.h>
23  *      #include <ccan/tal/link/link.h>
24  *      #include <ccan/tal/str/str.h>
25  *
26  *      struct upcache {
27  *              const char *str;
28  *              const char *upstr;
29  *      };
30  *
31  *      static struct upcache *cache;
32  *      static unsigned int cache_hits = 0;
33  *      #define CACHE_SIZE 4
34  *      static void init_upcase(void)
35  *      {
36  *              cache = tal_arrz(NULL, struct upcache, CACHE_SIZE);
37  *      }
38  *
39  *      static struct upcache *lookup_upcase(const char *str)
40  *      {
41  *              unsigned int i;
42  *              for (i = 0; i < CACHE_SIZE; i++)
43  *                      if (cache[i].str && !strcmp(cache[i].str, str)) {
44  *                              cache_hits++;
45  *                              return &cache[i];
46  *                      }
47  *              return NULL;
48  *      }
49  *
50  *      static struct upcache *new_upcase(const char *str)
51  *      {
52  *              unsigned int i;
53  *              char *upstr;
54  *
55  *              upstr = tal_linkable(tal_strdup(NULL, str));
56  *              i = random() % CACHE_SIZE;
57  *
58  *              // Throw out old: works fine if cache[i].upstr is NULL.
59  *              tal_delink(cache, cache[i].upstr);
60  *
61  *              // Replace with new.
62  *              cache[i].str = str;
63  *              cache[i].upstr = tal_link(cache, upstr);
64  *              while (*upstr) {
65  *                      *upstr = toupper(*upstr);
66  *                      upstr++;
67  *              }
68  *              return &cache[i];
69  *      }
70  *
71  *      // If you want to keep the result, tal_link it.
72  *      static const char *get_upcase(const char *str)
73  *      {
74  *              struct upcache *uc = lookup_upcase(str);
75  *              if (!uc)
76  *                      uc = new_upcase(str);
77  *              if (!uc)
78  *                      return NULL;
79  *              return uc->upstr;
80  *      }
81  *
82  *      static void exit_upcase(void)
83  *      {
84  *              tal_free(cache);
85  *              printf("%u cache hits ", cache_hits);
86  *      }
87  *
88  *      int main(int argc, char *argv[])
89  *      {
90  *              unsigned int i;
91  *              const char **values;
92  *
93  *              // Initialize cache.
94  *              init_upcase();
95  *
96  *              // Throw values in.
97  *              values = tal_arr(NULL, const char *, argc);
98  *              for (i = 1; i < argc; i++)
99  *                      values[i-1] = tal_link(values, get_upcase(argv[i]));
100  *
101  *              // This will free all the values, but cache will still work.
102  *              tal_free(values);
103  *
104  *              // Repeat!
105  *              values = tal_arr(NULL, const char *, argc);
106  *              for (i = 1; i < argc; i++)
107  *                      values[i-1] = tal_link(values, get_upcase(argv[i]));
108  *
109  *              // This will remove cache links, but we still have a link.
110  *              exit_upcase();
111  *
112  *              // Show values, so we output something.
113  *              for (i = 0; i < argc - 1; i++)
114  *                      printf("%s ", values[i]);
115  *              printf("\n");
116  *
117  *              // This will finally free the upcase strings (last link).
118  *              tal_free(values);
119  *
120  *              return 0;
121  *      }
122  *
123  * License: BSD-MIT
124  * Author: Rusty Russell <rusty@rustcorp.com.au>
125  */
126 int main(int argc, char *argv[])
127 {
128         if (argc != 2)
129                 return 1;
130
131         if (strcmp(argv[1], "depends") == 0) {
132                 printf("ccan/container_of\n");
133                 printf("ccan/list\n");
134                 printf("ccan/tal\n");
135                 return 0;
136         }
137
138         return 1;
139 }