tal/str: move tal string functions here from tal.
[ccan] / ccan / tal / _info
1 #include <stdio.h>
2 #include <string.h>
3 #include "config.h"
4
5 /**
6  * tal - compact tree allocator routines (inspired by talloc)
7  *
8  * Tal is a hierarchical allocator; any pointer allocated by tal can
9  * become the parent of another allocation.  When you free that parent,
10  * the children (and grandchildren, etc) are automatically freed.
11  *
12  * This allows you to build complex objects based on their lifetimes, eg:
13  *
14  *  struct foo *X = tal(NULL, struct foo);
15  *  X->val = tal(X, int);
16  *
17  * and the pointer X->val would be a "child" of the tal context "X";
18  * tal_free(X->val) would free X->val as expected, by tal_free(X) would
19  * free X and X->val.
20  *
21  * With an overhead of approximately 4 pointers per object
22  * (vs. talloc's 12 pointers), it uses dynamic allocation for
23  * destructors and child lists, so those operations can fail.  It does
24  * not support talloc's references or failing destructors.
25  *
26  * See Also:
27  *      ccan/tal/str (useful string helpers)
28  *
29  * Example:
30  *      #include <stdio.h>
31  *      #include <err.h>
32  *      #include <ccan/talloc/talloc.h>
33  *
34  *      // A structure containing a popened command.
35  *      struct command {
36  *              FILE *f;
37  *              char *command;
38  *      };
39  *
40  *      // When struct command is freed, we also want to pclose pipe.
41  *      static void close_cmd(struct command *cmd)
42  *      {
43  *              pclose(cmd->f);
44  *      }
45  *
46  *      // This function opens a writable pipe to the given command.
47  *      static struct command *open_output_cmd(const tal_t *ctx,
48  *                                             const char *a0, const char *a1)
49  *      {
50  *              struct command *cmd = tal(ctx, struct command);
51  *
52  *              if (!cmd)
53  *                      return NULL;
54  *
55  *              // Note that tal/str has helpers to make this much easier!
56  *              cmd->command = tal_arrz(cmd, char, strlen(a0) + strlen(a1) + 2);
57  *              if (!cmd->command) {
58  *                      tal_free(cmd);
59  *                      return NULL;
60  *              }
61  *              strcat(cmd->command, a0);
62  *              strcat(cmd->command, " ");
63  *              strcat(cmd->command, a1);
64  *
65  *              cmd->f = popen(cmd->command, "w");
66  *              if (!cmd->f) {
67  *                      tal_free(cmd);
68  *                      return NULL;
69  *              }
70  *              tal_add_destructor(cmd, close_cmd);
71  *              return cmd;
72  *      }
73  *
74  *      int main(int argc, char *argv[])
75  *      {
76  *              struct command *cmd;
77  *
78  *              if (argc != 2)
79  *                      errx(1, "Usage: %s <command>\n", argv[0]);
80  *
81  *              cmd = open_output_cmd(NULL, argv[1], "hello");
82  *              if (!cmd)
83  *                      err(1, "Running '%s hello'", argv[1]);
84  *              fprintf(cmd->f, "This is a test\n");
85  *              tal_free(cmd);
86  *              return 0;
87  *      }
88  *
89  * License: BSD-MIT
90  */
91 int main(int argc, char *argv[])
92 {
93         if (argc != 2)
94                 return 1;
95
96         if (strcmp(argv[1], "depends") == 0) {
97                 printf("ccan/compiler\n");
98                 printf("ccan/likely\n");
99                 printf("ccan/list\n");
100                 printf("ccan/str\n");
101                 printf("ccan/take\n");
102                 printf("ccan/typesafe_cb\n");
103                 return 0;
104         }
105
106         return 1;
107 }