mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 21:35:11 +01:00
ccan: remove unused modules.
These tal submodules got pulled in initially by an overzealous copy. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
7bebfe265c
commit
af8e4ed2b9
3
Makefile
3
Makefile
@ -126,12 +126,9 @@ CCAN_HEADERS := \
|
||||
$(CCANDIR)/ccan/structeq/structeq.h \
|
||||
$(CCANDIR)/ccan/take/take.h \
|
||||
$(CCANDIR)/ccan/tal/grab_file/grab_file.h \
|
||||
$(CCANDIR)/ccan/tal/link/link.h \
|
||||
$(CCANDIR)/ccan/tal/path/path.h \
|
||||
$(CCANDIR)/ccan/tal/stack/stack.h \
|
||||
$(CCANDIR)/ccan/tal/str/str.h \
|
||||
$(CCANDIR)/ccan/tal/tal.h \
|
||||
$(CCANDIR)/ccan/tal/talloc/talloc.h \
|
||||
$(CCANDIR)/ccan/tcon/tcon.h \
|
||||
$(CCANDIR)/ccan/time/time.h \
|
||||
$(CCANDIR)/ccan/timer/timer.h \
|
||||
|
@ -1 +0,0 @@
|
||||
../../../licenses/BSD-MIT
|
@ -1,139 +0,0 @@
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* tal/link - link helper for tal
|
||||
*
|
||||
* Tal does not support talloc-style references. In the cases where
|
||||
* an object needs multiple parents, all parents need to be aware of
|
||||
* the situation; thus tal/link is a helper where all "parents"
|
||||
* tal_link an object they agree to share ownership of.
|
||||
*
|
||||
* Example:
|
||||
* // Silly program which keeps a cache of uppercased strings.
|
||||
* // The cache wants to keep strings around even after they may have
|
||||
* // been "freed" by the caller.
|
||||
* // Given "hello" outputs "1 cache hits HELLO \n"
|
||||
* // Given "hello hello there" outputs "4 cache hits HELLO HELLO THERE \n"
|
||||
* #include <stdio.h>
|
||||
* #include <err.h>
|
||||
* #include <string.h>
|
||||
* #include <ctype.h>
|
||||
* #include <ccan/tal/link/link.h>
|
||||
* #include <ccan/tal/str/str.h>
|
||||
*
|
||||
* struct upcache {
|
||||
* const char *str;
|
||||
* const char *upstr;
|
||||
* };
|
||||
*
|
||||
* static struct upcache *cache;
|
||||
* static unsigned int cache_hits = 0;
|
||||
* #define CACHE_SIZE 4
|
||||
* static void init_upcase(void)
|
||||
* {
|
||||
* cache = tal_arrz(NULL, struct upcache, CACHE_SIZE);
|
||||
* }
|
||||
*
|
||||
* static struct upcache *lookup_upcase(const char *str)
|
||||
* {
|
||||
* unsigned int i;
|
||||
* for (i = 0; i < CACHE_SIZE; i++)
|
||||
* if (cache[i].str && !strcmp(cache[i].str, str)) {
|
||||
* cache_hits++;
|
||||
* return &cache[i];
|
||||
* }
|
||||
* return NULL;
|
||||
* }
|
||||
*
|
||||
* static struct upcache *new_upcase(const char *str)
|
||||
* {
|
||||
* unsigned int i;
|
||||
* char *upstr;
|
||||
*
|
||||
* upstr = tal_linkable(tal_strdup(NULL, str));
|
||||
* i = random() % CACHE_SIZE;
|
||||
*
|
||||
* // Throw out old: works fine if cache[i].upstr is NULL.
|
||||
* tal_delink(cache, cache[i].upstr);
|
||||
*
|
||||
* // Replace with new.
|
||||
* cache[i].str = str;
|
||||
* cache[i].upstr = tal_link(cache, upstr);
|
||||
* while (*upstr) {
|
||||
* *upstr = toupper(*upstr);
|
||||
* upstr++;
|
||||
* }
|
||||
* return &cache[i];
|
||||
* }
|
||||
*
|
||||
* // If you want to keep the result, tal_link it.
|
||||
* static const char *get_upcase(const char *str)
|
||||
* {
|
||||
* struct upcache *uc = lookup_upcase(str);
|
||||
* if (!uc)
|
||||
* uc = new_upcase(str);
|
||||
* if (!uc)
|
||||
* return NULL;
|
||||
* return uc->upstr;
|
||||
* }
|
||||
*
|
||||
* static void exit_upcase(void)
|
||||
* {
|
||||
* tal_free(cache);
|
||||
* printf("%u cache hits ", cache_hits);
|
||||
* }
|
||||
*
|
||||
* int main(int argc, char *argv[])
|
||||
* {
|
||||
* unsigned int i;
|
||||
* const char **values;
|
||||
*
|
||||
* // Initialize cache.
|
||||
* init_upcase();
|
||||
*
|
||||
* // Throw values in.
|
||||
* values = tal_arr(NULL, const char *, argc);
|
||||
* for (i = 1; i < argc; i++)
|
||||
* values[i-1] = tal_link(values, get_upcase(argv[i]));
|
||||
*
|
||||
* // This will free all the values, but cache will still work.
|
||||
* tal_free(values);
|
||||
*
|
||||
* // Repeat!
|
||||
* values = tal_arr(NULL, const char *, argc);
|
||||
* for (i = 1; i < argc; i++)
|
||||
* values[i-1] = tal_link(values, get_upcase(argv[i]));
|
||||
*
|
||||
* // This will remove cache links, but we still have a link.
|
||||
* exit_upcase();
|
||||
*
|
||||
* // Show values, so we output something.
|
||||
* for (i = 0; i < argc - 1; i++)
|
||||
* printf("%s ", values[i]);
|
||||
* printf("\n");
|
||||
*
|
||||
* // This will finally free the upcase strings (last link).
|
||||
* tal_free(values);
|
||||
*
|
||||
* return 0;
|
||||
* }
|
||||
*
|
||||
* License: BSD-MIT
|
||||
* Author: Rusty Russell <rusty@rustcorp.com.au>
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
return 1;
|
||||
|
||||
if (strcmp(argv[1], "depends") == 0) {
|
||||
printf("ccan/container_of\n");
|
||||
printf("ccan/list\n");
|
||||
printf("ccan/tal\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
/* Licensed under BSD-MIT - see LICENSE file for details */
|
||||
#include <ccan/tal/link/link.h>
|
||||
#include <ccan/container_of/container_of.h>
|
||||
#include <ccan/list/list.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* Our linkable parent. */
|
||||
struct linkable {
|
||||
struct list_head links;
|
||||
};
|
||||
|
||||
struct link {
|
||||
struct list_node list;
|
||||
};
|
||||
|
||||
static void linkable_notifier(tal_t *linkable,
|
||||
enum tal_notify_type type,
|
||||
void *info)
|
||||
{
|
||||
struct linkable *l = tal_parent(linkable);
|
||||
assert(type == TAL_NOTIFY_STEAL || type == TAL_NOTIFY_FREE);
|
||||
|
||||
/* We let you free it if you haven't linked it yet. */
|
||||
if (type == TAL_NOTIFY_FREE && list_empty(&l->links)) {
|
||||
tal_free(l);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Don't try to steal or free this: it has multiple links! */
|
||||
abort();
|
||||
}
|
||||
|
||||
void *tal_linkable_(tal_t *newobj)
|
||||
{
|
||||
struct linkable *l;
|
||||
|
||||
/* Must be a fresh object. */
|
||||
assert(!tal_parent(newobj));
|
||||
|
||||
l = tal(NULL, struct linkable);
|
||||
if (!l)
|
||||
goto fail;
|
||||
list_head_init(&l->links);
|
||||
|
||||
if (!tal_steal(l, newobj))
|
||||
goto fail;
|
||||
|
||||
if (!tal_add_notifier(newobj, TAL_NOTIFY_STEAL|TAL_NOTIFY_FREE,
|
||||
linkable_notifier)) {
|
||||
tal_steal(NULL, newobj);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return (void *)newobj;
|
||||
|
||||
fail:
|
||||
tal_free(l);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void destroy_link(struct link *lnk)
|
||||
{
|
||||
struct linkable *l;
|
||||
|
||||
/* Only true if we're first in list! */
|
||||
l = container_of(lnk->list.prev, struct linkable, links.n);
|
||||
|
||||
list_del(&lnk->list);
|
||||
|
||||
if (list_empty(&l->links))
|
||||
tal_free(l);
|
||||
}
|
||||
|
||||
void *tal_link_(const tal_t *ctx, const tal_t *link)
|
||||
{
|
||||
struct linkable *l = tal_parent(link);
|
||||
struct link *lnk = tal(ctx, struct link);
|
||||
|
||||
if (!lnk)
|
||||
return NULL;
|
||||
if (!tal_add_destructor(lnk, destroy_link)) {
|
||||
tal_free(lnk);
|
||||
return NULL;
|
||||
}
|
||||
list_add(&l->links, &lnk->list);
|
||||
return (void *)link;
|
||||
}
|
||||
|
||||
void tal_delink_(const tal_t *ctx, const tal_t *link)
|
||||
{
|
||||
struct linkable *l = tal_parent(link);
|
||||
struct link *i;
|
||||
|
||||
if (!link)
|
||||
return;
|
||||
|
||||
/* FIXME: slow, but hopefully unusual. */
|
||||
list_for_each(&l->links, i, list) {
|
||||
if (tal_parent(i) == ctx) {
|
||||
tal_free(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
abort();
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
/* Licensed under BSD-MIT - see LICENSE file for details */
|
||||
#ifndef TAL_LINK_H
|
||||
#define TAL_LINK_H
|
||||
#include "config.h"
|
||||
#include <ccan/tal/tal.h>
|
||||
|
||||
/**
|
||||
* tal_linkable - set up a tal object to be linkable.
|
||||
* @newobj - the newly allocated object (with a NULL parent)
|
||||
*
|
||||
* The object will be freed when @newobj is freed or the last tal_link()
|
||||
* is tal_delink'ed.
|
||||
*
|
||||
* Returns @newobj or NULL (if an allocation fails).
|
||||
*
|
||||
* Example:
|
||||
* int *shared_count;
|
||||
*
|
||||
* shared_count = tal_linkable(talz(NULL, int));
|
||||
* assert(shared_count);
|
||||
*/
|
||||
#define tal_linkable(newobj) \
|
||||
(tal_typeof(newobj) tal_linkable_((newobj)))
|
||||
|
||||
/**
|
||||
* tal_link - add a(nother) link to a linkable object.
|
||||
* @ctx - the context to link to (parent of the resulting link)
|
||||
* @obj - the object previously made linkable with tal_linked().
|
||||
*
|
||||
* If @ctx is non-NULL, the link will be a child of @ctx, and this freed
|
||||
* when @ctx is.
|
||||
*
|
||||
* Returns NULL on failure (out of memory).
|
||||
*
|
||||
* Example:
|
||||
* void *my_ctx = NULL;
|
||||
*
|
||||
* tal_link(my_ctx, shared_count);
|
||||
*/
|
||||
#if HAVE_STATEMENT_EXPR
|
||||
/* Weird macro avoids gcc's 'warning: value computed is not used'. */
|
||||
#define tal_link(ctx, obj) \
|
||||
({ tal_typeof(obj) tal_link_((ctx), (obj)); })
|
||||
#else
|
||||
#define tal_link(ctx, obj) \
|
||||
(tal_typeof(obj) tal_link_((ctx), (obj)))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* tal_delink - explicitly remove a link from a linkable object.
|
||||
* @ctx - the context to link to (parent of the resulting link)
|
||||
* @obj - the object previously made linkable with tal_linked().
|
||||
*
|
||||
* Explicitly remove a link: normally it is implied by freeing @ctx.
|
||||
* Removing the last link frees the object. If @obj is NULL, nothing
|
||||
* is done.
|
||||
*
|
||||
* Example:
|
||||
* tal_delink(my_ctx, shared_count);
|
||||
*/
|
||||
#define tal_delink(ctx, obj) \
|
||||
tal_delink_((ctx), (obj))
|
||||
|
||||
/* Internal helpers. */
|
||||
void *tal_linkable_(tal_t *newobj);
|
||||
void *tal_link_(const tal_t *ctx, const tal_t *dest);
|
||||
void tal_delink_(const tal_t *ctx, const tal_t *dest);
|
||||
|
||||
#endif /* TAL_LINK_H */
|
@ -1,73 +0,0 @@
|
||||
#include <ccan/tal/link/link.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
#include <stdlib.h>
|
||||
#include <err.h>
|
||||
|
||||
static unsigned int destroy_count = 0;
|
||||
static void destroy_obj(void *obj)
|
||||
{
|
||||
destroy_count++;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *linkable, *p1, *p2, *p3;
|
||||
void **voidpp;
|
||||
|
||||
plan_tests(23);
|
||||
|
||||
linkable = tal(NULL, char);
|
||||
ok1(tal_linkable(linkable) == linkable);
|
||||
ok1(tal_add_destructor(linkable, destroy_obj));
|
||||
/* First, free it immediately. */
|
||||
tal_free(linkable);
|
||||
ok1(destroy_count == 1);
|
||||
|
||||
/* Now create and remove a single link. */
|
||||
linkable = tal_linkable(tal(NULL, char));
|
||||
ok1(tal_add_destructor(linkable, destroy_obj));
|
||||
ok1(p1 = tal_link(NULL, linkable));
|
||||
ok1(p1 == linkable);
|
||||
tal_delink(NULL, linkable);
|
||||
ok1(destroy_count == 2);
|
||||
|
||||
/* Two links.*/
|
||||
linkable = tal_linkable(tal(NULL, char));
|
||||
ok1(tal_add_destructor(linkable, destroy_obj));
|
||||
ok1(p1 = tal_link(NULL, linkable));
|
||||
ok1(p1 == linkable);
|
||||
ok1(p2 = tal_link(NULL, linkable));
|
||||
ok1(p2 == linkable);
|
||||
tal_delink(NULL, linkable);
|
||||
tal_delink(NULL, linkable);
|
||||
ok1(destroy_count == 3);
|
||||
|
||||
/* Three links.*/
|
||||
linkable = tal_linkable(tal(NULL, char));
|
||||
ok1(tal_add_destructor(linkable, destroy_obj));
|
||||
ok1(p1 = tal_link(NULL, linkable));
|
||||
ok1(p1 == linkable);
|
||||
ok1(p2 = tal_link(NULL, linkable));
|
||||
ok1(p2 == linkable);
|
||||
ok1(p3 = tal_link(NULL, linkable));
|
||||
ok1(p3 == linkable);
|
||||
tal_delink(NULL, linkable);
|
||||
tal_delink(NULL, linkable);
|
||||
tal_delink(NULL, linkable);
|
||||
ok1(destroy_count == 4);
|
||||
|
||||
/* Now, indirectly. */
|
||||
voidpp = tal(NULL, void *);
|
||||
linkable = tal_linkable(tal(NULL, char));
|
||||
ok1(tal_add_destructor(linkable, destroy_obj));
|
||||
/* Suppress gratuitous warning with tests_compile_without_features */
|
||||
#if HAVE_STATEMENT_EXPR
|
||||
tal_link(voidpp, linkable);
|
||||
#else
|
||||
(void)tal_link(voidpp, linkable);
|
||||
#endif
|
||||
tal_free(voidpp);
|
||||
ok1(destroy_count == 5);
|
||||
|
||||
return exit_status();
|
||||
}
|
@ -1 +0,0 @@
|
||||
../../../licenses/BSD-MIT
|
@ -1,68 +0,0 @@
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* tal/stack - stack of tal contextes (inspired by talloc_stack)
|
||||
*
|
||||
* Implement a stack of tal contexts. A new (empty) context is pushed on top
|
||||
* of the stack using tal_newframe and it is popped/freed using tal_free().
|
||||
* tal_curframe() can be used to get the stack's top context.
|
||||
*
|
||||
* tal_stack can be used to implement per-function temporary allocation context
|
||||
* to help mitigating memory leaks, but unlike the plain tal approach it does not
|
||||
* require the caller to pass a destination context for returning allocated
|
||||
* values. Instead, allocated values are moved to the parent context using
|
||||
* tal_steal(tal_parent(tmp_ctx), ptr).
|
||||
*
|
||||
* Example:
|
||||
* #include <assert.h>
|
||||
* #include <ccan/tal/stack/stack.h>
|
||||
*
|
||||
* static int *do_work(void)
|
||||
* {
|
||||
* int *retval = NULL;
|
||||
* tal_t *tmp_ctx = tal_newframe();
|
||||
*
|
||||
* int *val = talz(tmp_ctx, int);
|
||||
* assert(val != NULL);
|
||||
*
|
||||
* // ... do something with val ...
|
||||
*
|
||||
* if (retval >= 0) {
|
||||
* // steal to parent cxt so it survives tal_free()
|
||||
* tal_steal(tal_parent(tmp_ctx), val);
|
||||
* retval = val;
|
||||
* }
|
||||
* tal_free(tmp_ctx);
|
||||
* return retval;
|
||||
* }
|
||||
*
|
||||
* int main(int argc, char *argv[])
|
||||
* {
|
||||
* tal_t *tmp_ctx = tal_newframe();
|
||||
* int *val = do_work();
|
||||
* if (val) {
|
||||
* // ... do something with val ...
|
||||
* }
|
||||
* // val is eventually freed
|
||||
* tal_free(tmp_ctx);
|
||||
* return 0;
|
||||
* }
|
||||
*
|
||||
* License: BSD-MIT
|
||||
* Author: Delio Brignoli <brignoli.delio@gmail.com>
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/* Expect exactly one argument */
|
||||
if (argc != 2)
|
||||
return 1;
|
||||
|
||||
if (strcmp(argv[1], "depends") == 0) {
|
||||
printf("ccan/tal\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
/* Licensed under BSD-MIT - see LICENSE file for details */
|
||||
|
||||
#include <ccan/tal/stack/stack.h>
|
||||
#include <assert.h>
|
||||
|
||||
static tal_t *h = NULL;
|
||||
|
||||
static void _free_frame(tal_t *o)
|
||||
{
|
||||
h = tal_parent(o);
|
||||
}
|
||||
|
||||
tal_t *tal_newframe_(const char *label)
|
||||
{
|
||||
h = tal_alloc_(h, 0, false, label);
|
||||
assert(h != NULL);
|
||||
tal_add_destructor(h, _free_frame);
|
||||
return h;
|
||||
}
|
||||
|
||||
tal_t *tal_curframe(void)
|
||||
{
|
||||
return h;
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
/* Licensed under BSD-MIT - see LICENSE file for details */
|
||||
#ifndef CCAN_TAL_STACK_H
|
||||
#define CCAN_TAL_STACK_H
|
||||
|
||||
#include <ccan/tal/tal.h>
|
||||
|
||||
/**
|
||||
* tal_newframe - allocate and return a new nested tal context
|
||||
*
|
||||
* Allocates and push a new tal context on top of the stack.
|
||||
* The context must be freed using tal_free() which will also pop it
|
||||
* off the stack, which will also free all its nested contextes, if any.
|
||||
*
|
||||
* NOTE: this function is not threadsafe.
|
||||
*
|
||||
* Example:
|
||||
* tal_t *ctx = tal_newframe();
|
||||
* // ... do something with ctx ...
|
||||
* tal_free(ctx);
|
||||
*/
|
||||
#define tal_newframe(void) tal_newframe_(TAL_LABEL(tal_stack, ""));
|
||||
|
||||
tal_t *tal_newframe_(const char *label);
|
||||
|
||||
/**
|
||||
* tal_curframe - return the current 'tal_stack frame'
|
||||
*
|
||||
* Returns the context currently on top of the stack. The initial context
|
||||
* (before any tal_newframe() call) is the tal 'NULL' context.
|
||||
*
|
||||
* NOTE: this function is not threadsafe.
|
||||
*/
|
||||
tal_t *tal_curframe(void);
|
||||
#endif /* CCAN_TAL_STACK_H */
|
@ -1,35 +0,0 @@
|
||||
#include <ccan/tal/stack/stack.h>
|
||||
#include <ccan/tal/stack/stack.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
tal_t *parent, *cur;
|
||||
|
||||
plan_tests(8);
|
||||
|
||||
/* initial frame is NULL */
|
||||
ok1(tal_curframe() == NULL);
|
||||
|
||||
/* create new frame and make sure all is OK */
|
||||
cur = tal_newframe();
|
||||
ok1(tal_curframe() == cur);
|
||||
ok1(tal_parent(cur) == NULL);
|
||||
|
||||
/* create another frame */
|
||||
parent = cur;
|
||||
cur = tal_newframe();
|
||||
ok1(tal_curframe() == cur);
|
||||
ok1(tal_parent(cur) == parent);
|
||||
|
||||
/* unwind */
|
||||
tal_free(cur);
|
||||
ok1(tal_curframe() == parent);
|
||||
cur = tal_curframe();
|
||||
ok1(tal_parent(cur) == NULL);
|
||||
tal_free(cur);
|
||||
ok1(tal_curframe() == NULL);
|
||||
|
||||
tal_cleanup();
|
||||
return exit_status();
|
||||
}
|
@ -1 +0,0 @@
|
||||
../../../licenses/LGPL-3
|
@ -1,43 +0,0 @@
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* tal/talloc - an implementation of the tal interface in terms of talloc.
|
||||
*
|
||||
* Tal and talloc are both hierarchical allocators, but have different APIs.
|
||||
* The tal API is mostly a subset of talloc, but if your project already
|
||||
* uses talloc then having both tal and talloc pointers is confusing, and
|
||||
* a waste of resources.
|
||||
*
|
||||
* The standard convention to tell ccan modules to use this instead of
|
||||
* ccan/tal is to define TAL_USE_TALLOC, usually on the commandline.
|
||||
*
|
||||
* Bugs:
|
||||
* tal_first() and tal_next() can't be implemented.
|
||||
* tal_set_backend() can only change the error function.
|
||||
*
|
||||
* License: LGPL
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
return 1;
|
||||
|
||||
if (strcmp(argv[1], "depends") == 0) {
|
||||
printf("ccan/take\n");
|
||||
printf("ccan/typesafe_cb\n");
|
||||
printf("ccan/compiler\n");
|
||||
printf("ccan/likely\n");
|
||||
printf("ccan/str\n");
|
||||
printf("talloc\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "libs") == 0) {
|
||||
printf("talloc\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
@ -1,263 +0,0 @@
|
||||
/* Licensed under LGPL - see LICENSE file for details */
|
||||
#include <ccan/tal/talloc/talloc.h>
|
||||
#include <ccan/take/take.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
static void (*errorfn)(const char *msg) = (void *)abort;
|
||||
|
||||
static void COLD call_error(const char *msg)
|
||||
{
|
||||
errorfn(msg);
|
||||
}
|
||||
|
||||
static void *error_on_null(void *p, const char *msg)
|
||||
{
|
||||
if (!p)
|
||||
call_error(msg);
|
||||
return p;
|
||||
}
|
||||
|
||||
void *tal_talloc_(const tal_t *ctx, size_t bytes, bool clear,
|
||||
const char *label)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
if (clear)
|
||||
ret = _talloc_zero(ctx, bytes, label);
|
||||
else
|
||||
ret = talloc_named_const(ctx, bytes, label);
|
||||
|
||||
return error_on_null(ret, "allocation failure");
|
||||
}
|
||||
|
||||
void *tal_talloc_arr_(const tal_t *ctx, size_t bytes, size_t count, bool clear,
|
||||
const char *label)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
if (clear)
|
||||
ret = _talloc_zero_array(ctx, bytes, count, label);
|
||||
else
|
||||
ret = _talloc_array(ctx, bytes, count, label);
|
||||
|
||||
return error_on_null(ret, "array allocation failure");
|
||||
}
|
||||
|
||||
void *tal_talloc_free_(const tal_t *ctx)
|
||||
{
|
||||
int saved_errno = errno;
|
||||
talloc_free((void *)ctx);
|
||||
errno = saved_errno;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool tal_talloc_set_name_(tal_t *ctx, const char *name, bool literal)
|
||||
{
|
||||
if (!literal) {
|
||||
name = talloc_strdup(ctx, name);
|
||||
if (!name) {
|
||||
call_error("set_name allocation failure");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
talloc_set_name_const(ctx, name);
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *tal_talloc_name_(const tal_t *ctx)
|
||||
{
|
||||
const char *p = talloc_get_name(ctx);
|
||||
if (p && unlikely(strcmp(p, "UNNAMED") == 0))
|
||||
p = NULL;
|
||||
return p;
|
||||
}
|
||||
|
||||
static bool adjust_size(size_t *size, size_t count)
|
||||
{
|
||||
/* Multiplication wrap */
|
||||
if (count && unlikely(*size * count / *size != count))
|
||||
goto overflow;
|
||||
|
||||
*size *= count;
|
||||
|
||||
/* Make sure we don't wrap adding header. */
|
||||
if (*size + 1024 < 1024)
|
||||
goto overflow;
|
||||
return true;
|
||||
overflow:
|
||||
call_error("allocation size overflow");
|
||||
return false;
|
||||
}
|
||||
|
||||
void *tal_talloc_dup_(const tal_t *ctx, const void *p, size_t size,
|
||||
size_t n, size_t extra, const char *label)
|
||||
{
|
||||
void *ret;
|
||||
size_t nbytes = size;
|
||||
|
||||
if (!adjust_size(&nbytes, n)) {
|
||||
if (taken(p))
|
||||
tal_free(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Beware addition overflow! */
|
||||
if (n + extra < n) {
|
||||
call_error("dup size overflow");
|
||||
if (taken(p))
|
||||
tal_free(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (taken(p)) {
|
||||
if (unlikely(!p))
|
||||
return NULL;
|
||||
if (unlikely(!tal_talloc_resize_((void **)&p, size, n + extra)))
|
||||
return tal_free(p);
|
||||
if (unlikely(!tal_steal(ctx, p)))
|
||||
return tal_free(p);
|
||||
return (void *)p;
|
||||
}
|
||||
|
||||
ret = tal_talloc_arr_(ctx, size, n + extra, false, label);
|
||||
if (ret)
|
||||
memcpy(ret, p, nbytes);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool tal_talloc_resize_(tal_t **ctxp, size_t size, size_t count)
|
||||
{
|
||||
tal_t *newp;
|
||||
|
||||
if (unlikely(count == 0)) {
|
||||
/* Don't free it! */
|
||||
newp = talloc_size(talloc_parent(*ctxp), 0);
|
||||
if (!newp) {
|
||||
call_error("Resize failure");
|
||||
return false;
|
||||
}
|
||||
talloc_free(*ctxp);
|
||||
*ctxp = newp;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* count is unsigned, not size_t, so check for overflow here! */
|
||||
if ((unsigned)count != count) {
|
||||
call_error("Resize overflos");
|
||||
return false;
|
||||
}
|
||||
|
||||
newp = _talloc_realloc_array(NULL, *ctxp, size, count, NULL);
|
||||
if (!newp) {
|
||||
call_error("Resize failure");
|
||||
return false;
|
||||
}
|
||||
*ctxp = newp;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tal_talloc_expand_(tal_t **ctxp, const void *src, size_t size, size_t count)
|
||||
{
|
||||
bool ret = false;
|
||||
size_t old_count = talloc_get_size(*ctxp) / size;
|
||||
|
||||
/* Check for additive overflow */
|
||||
if (old_count + count < count) {
|
||||
call_error("dup size overflow");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Don't point src inside thing we're expanding! */
|
||||
assert(src < *ctxp
|
||||
|| (char *)src >= (char *)(*ctxp) + (size * old_count));
|
||||
|
||||
if (!tal_talloc_resize_(ctxp, size, old_count + count))
|
||||
goto out;
|
||||
|
||||
memcpy((char *)*ctxp + size * old_count, src, count * size);
|
||||
ret = true;
|
||||
|
||||
out:
|
||||
if (taken(src))
|
||||
tal_free(src);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Sucky inline hash table implementation, to avoid deps. */
|
||||
#define HTABLE_BITS 10
|
||||
struct destructor {
|
||||
struct destructor *next;
|
||||
const tal_t *ctx;
|
||||
void (*destroy)(void *me);
|
||||
};
|
||||
static struct destructor *destr_hash[1 << HTABLE_BITS];
|
||||
|
||||
static unsigned int hash_ptr(const void *p)
|
||||
{
|
||||
unsigned long h = (unsigned long)p / sizeof(void *);
|
||||
|
||||
return (h ^ (h >> HTABLE_BITS)) & ((1 << HTABLE_BITS) - 1);
|
||||
}
|
||||
|
||||
static int tal_talloc_destroy(const tal_t *ctx)
|
||||
{
|
||||
struct destructor **d = &destr_hash[hash_ptr(ctx)];
|
||||
while (*d) {
|
||||
if ((*d)->ctx == ctx) {
|
||||
struct destructor *this = *d;
|
||||
this->destroy((void *)ctx);
|
||||
*d = this->next;
|
||||
talloc_free(this);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool tal_talloc_add_destructor_(const tal_t *ctx, void (*destroy)(void *me))
|
||||
{
|
||||
struct destructor *d = talloc(ctx, struct destructor);
|
||||
if (!d)
|
||||
return false;
|
||||
|
||||
d->next = destr_hash[hash_ptr(ctx)];
|
||||
d->ctx = ctx;
|
||||
d->destroy = destroy;
|
||||
destr_hash[hash_ptr(ctx)] = d;
|
||||
talloc_set_destructor(ctx, tal_talloc_destroy);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tal_talloc_del_destructor_(const tal_t *ctx, void (*destroy)(void *me))
|
||||
{
|
||||
struct destructor **d = &destr_hash[hash_ptr(ctx)];
|
||||
|
||||
while (*d) {
|
||||
if ((*d)->ctx == ctx && (*d)->destroy == destroy) {
|
||||
struct destructor *this = *d;
|
||||
*d = this->next;
|
||||
talloc_free(this);
|
||||
return true;
|
||||
}
|
||||
d = &(*d)->next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void tal_talloc_set_backend_(void *(*alloc_fn)(size_t size),
|
||||
void *(*resize_fn)(void *, size_t size),
|
||||
void (*free_fn)(void *),
|
||||
void (*error_fn)(const char *msg))
|
||||
{
|
||||
assert(!alloc_fn);
|
||||
assert(!resize_fn);
|
||||
assert(!free_fn);
|
||||
errorfn = error_fn;
|
||||
talloc_set_abort_fn(error_fn);
|
||||
}
|
||||
|
||||
bool tal_talloc_check_(const tal_t *ctx, const char *errorstr)
|
||||
{
|
||||
/* We can't really check, but this iterates (and may abort). */
|
||||
return !ctx || talloc_total_blocks(ctx) >= 1;
|
||||
}
|
@ -1,316 +0,0 @@
|
||||
/* Licensed under LGPL - see LICENSE file for details */
|
||||
#ifndef CCAN_TAL_TALLOC_H
|
||||
#define CCAN_TAL_TALLOC_H
|
||||
#include "config.h"
|
||||
#include <ccan/compiler/compiler.h>
|
||||
#include <ccan/likely/likely.h>
|
||||
#include <ccan/typesafe_cb/typesafe_cb.h>
|
||||
#include <ccan/str/str.h>
|
||||
#include <talloc.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/**
|
||||
* tal_t - convenient alias for void to mark tal pointers.
|
||||
*
|
||||
* Since any pointer can be a tal-allocated pointer, it's often
|
||||
* useful to use this typedef to mark them explicitly.
|
||||
*/
|
||||
typedef TALLOC_CTX tal_t;
|
||||
|
||||
/**
|
||||
* tal - basic allocator function
|
||||
* @ctx: NULL, or tal allocated object to be parent.
|
||||
* @type: the type to allocate.
|
||||
*
|
||||
* Allocates a specific type, with a given parent context. The name
|
||||
* of the object is a string of the type, but if CCAN_TAL_DEBUG is
|
||||
* defined it also contains the file and line which allocated it.
|
||||
*
|
||||
* Example:
|
||||
* int *p = tal(NULL, int);
|
||||
* *p = 1;
|
||||
*/
|
||||
#define tal(ctx, type) \
|
||||
((type *)tal_talloc_((ctx), sizeof(type), false, \
|
||||
TAL_LABEL(type, "")))
|
||||
|
||||
/**
|
||||
* talz - zeroing allocator function
|
||||
* @ctx: NULL, or tal allocated object to be parent.
|
||||
* @type: the type to allocate.
|
||||
*
|
||||
* Equivalent to tal() followed by memset() to zero.
|
||||
*
|
||||
* Example:
|
||||
* p = talz(NULL, int);
|
||||
* assert(*p == 0);
|
||||
*/
|
||||
#define talz(ctx, type) \
|
||||
((type *)tal_talloc_((ctx), sizeof(type), true, \
|
||||
TAL_LABEL(type, "")))
|
||||
|
||||
/**
|
||||
* tal_free - free a tal-allocated pointer.
|
||||
* @p: NULL, or tal allocated object to free.
|
||||
*
|
||||
* This calls the destructors for p (if any), then does the same for all its
|
||||
* children (recursively) before finally freeing the memory. It returns
|
||||
* NULL, for convenience.
|
||||
*
|
||||
* Note: errno is preserved by this call.
|
||||
*
|
||||
* Example:
|
||||
* p = tal_free(p);
|
||||
*/
|
||||
#define tal_free(p) tal_talloc_free_(p)
|
||||
|
||||
/**
|
||||
* tal_arr - allocate an array of objects.
|
||||
* @ctx: NULL, or tal allocated object to be parent.
|
||||
* @type: the type to allocate.
|
||||
* @count: the number to allocate.
|
||||
*
|
||||
* Note that an object allocated with tal_arr() has a length property;
|
||||
* see tal_count().
|
||||
*
|
||||
* Example:
|
||||
* p = tal_arr(NULL, int, 2);
|
||||
* p[0] = 0;
|
||||
* p[1] = 1;
|
||||
*/
|
||||
#define tal_arr(ctx, type, count) \
|
||||
((type *)tal_talloc_arr_((ctx), sizeof(type), (count), false, \
|
||||
TAL_LABEL(type, "[]")))
|
||||
|
||||
/**
|
||||
* tal_arrz - allocate an array of zeroed objects.
|
||||
* @ctx: NULL, or tal allocated object to be parent.
|
||||
* @type: the type to allocate.
|
||||
* @count: the number to allocate.
|
||||
*
|
||||
* Note that an object allocated with tal_arrz() has a length property;
|
||||
* see tal_count().
|
||||
*
|
||||
* Example:
|
||||
* p = tal_arrz(NULL, int, 2);
|
||||
* assert(p[0] == 0 && p[1] == 0);
|
||||
*/
|
||||
#define tal_arrz(ctx, type, count) \
|
||||
((type *)tal_talloc_arr_((ctx), sizeof(type), (count), true, \
|
||||
TAL_LABEL(type, "[]")))
|
||||
|
||||
/**
|
||||
* tal_resize - enlarge or reduce a tal_arr[z].
|
||||
* @p: A pointer to the tal allocated array to resize.
|
||||
* @count: the number to allocate.
|
||||
*
|
||||
* This returns true on success (and may move *@p), or false on failure.
|
||||
* If @p has a length property, it is updated on success.
|
||||
*
|
||||
* Example:
|
||||
* tal_resize(&p, 100);
|
||||
*/
|
||||
#define tal_resize(p, count) \
|
||||
tal_talloc_resize_((void **)(p), sizeof**(p), (count))
|
||||
|
||||
/**
|
||||
* tal_steal - change the parent of a tal-allocated pointer.
|
||||
* @ctx: The new parent.
|
||||
* @ptr: The tal allocated object to move.
|
||||
*
|
||||
* This may need to perform an allocation, in which case it may fail; thus
|
||||
* it can return NULL, otherwise returns @ptr.
|
||||
*/
|
||||
#define tal_steal(ctx, ptr) talloc_steal((ctx), (ptr))
|
||||
|
||||
/**
|
||||
* tal_add_destructor - add a callback function when this context is destroyed.
|
||||
* @ptr: The tal allocated object.
|
||||
* @function: the function to call before it's freed.
|
||||
*
|
||||
* This is a more convenient form of tal_add_notifier(@ptr,
|
||||
* TAL_NOTIFY_FREE, ...), in that the function prototype takes only @ptr.
|
||||
*/
|
||||
#define tal_add_destructor(ptr, function) \
|
||||
tal_talloc_add_destructor_((ptr), typesafe_cb(void, void *, \
|
||||
(function), (ptr)))
|
||||
|
||||
/**
|
||||
* tal_del_destructor - remove a destructor callback function.
|
||||
* @ptr: The tal allocated object.
|
||||
* @function: the function to call before it's freed.
|
||||
*
|
||||
* If @function has not been successfully added as a destructor, this returns
|
||||
* false.
|
||||
*
|
||||
* Note: you can't add more than one destructor with the talloc backend!
|
||||
*/
|
||||
#define tal_del_destructor(ptr, function) \
|
||||
tal_talloc_del_destructor_((ptr), typesafe_cb(void, void *, \
|
||||
(function), (ptr)))
|
||||
|
||||
/**
|
||||
* tal_set_name - attach a name to a tal pointer.
|
||||
* @ptr: The tal allocated object.
|
||||
* @name: The name to use.
|
||||
*
|
||||
* The name is copied, unless we're certain it's a string literal.
|
||||
*/
|
||||
#define tal_set_name(ptr, name) \
|
||||
tal_talloc_set_name_((ptr), (name), TAL_TALLOC_IS_LITERAL(name))
|
||||
|
||||
/**
|
||||
* tal_name - get the name for a tal pointer.
|
||||
* @ptr: The tal allocated object.
|
||||
*
|
||||
* Returns NULL if no name has been set.
|
||||
*/
|
||||
#define tal_name(ptr) \
|
||||
tal_talloc_name_(ptr)
|
||||
|
||||
/**
|
||||
* tal_count - get the count of objects in a tal_arr.
|
||||
* @ptr: The tal allocated object array.
|
||||
*/
|
||||
#define tal_count(ptr) talloc_array_length(ptr)
|
||||
|
||||
/**
|
||||
* tal_parent - get the parent of a tal object.
|
||||
* @ctx: The tal allocated object.
|
||||
*
|
||||
* Returns the parent, which may be NULL. Returns NULL if @ctx is NULL.
|
||||
*/
|
||||
#define tal_parent(ctx) talloc_parent(ctx)
|
||||
|
||||
/**
|
||||
* tal_dup - duplicate an object.
|
||||
* @ctx: The tal allocated object to be parent of the result (may be NULL).
|
||||
* @type: the type (should match type of @p!)
|
||||
* @p: the object to copy (or reparented if take())
|
||||
*/
|
||||
#define tal_dup(ctx, type, p) \
|
||||
((type *)tal_talloc_dup_((ctx), tal_talloc_typechk_(p, type *), \
|
||||
sizeof(type), 1, 0, \
|
||||
TAL_LABEL(type, "")))
|
||||
|
||||
/**
|
||||
* tal_dup_arr - duplicate an array.
|
||||
* @ctx: The tal allocated object to be parent of the result (may be NULL).
|
||||
* @type: the type (should match type of @p!)
|
||||
* @p: the array to copy (or resized & reparented if take())
|
||||
* @n: the number of sizeof(type) entries to copy.
|
||||
* @extra: the number of extra sizeof(type) entries to allocate.
|
||||
*/
|
||||
#define tal_dup_arr(ctx, type, p, n, extra) \
|
||||
((type *)tal_talloc_dup_((ctx), tal_talloc_typechk_(p, type *), \
|
||||
sizeof(type), (n), (extra), \
|
||||
TAL_LABEL(type, "[]")))
|
||||
|
||||
|
||||
/**
|
||||
* tal_set_backend - set the allocation or error functions to use
|
||||
* @alloc_fn: NULL
|
||||
* @resize_fn: NULL
|
||||
* @free_fn: NULL
|
||||
* @error_fn: called on errors or NULL (default is abort)
|
||||
*
|
||||
* The defaults are set up so tal functions never return NULL, but you
|
||||
* can override error_fn to change that. error_fn can return, and is
|
||||
* called if malloc or realloc fail.
|
||||
*/
|
||||
#define tal_set_backend(alloc_fn, resize_fn, free_fn, error_fn) \
|
||||
tal_talloc_set_backend_((alloc_fn), (resize_fn), (free_fn), (error_fn))
|
||||
|
||||
/**
|
||||
* tal_expand - expand a tal array with contents.
|
||||
* @a1p: a pointer to the tal array to expand.
|
||||
* @a2: the second array (can be take()).
|
||||
* @num2: the number of elements in the second array.
|
||||
*
|
||||
* Note that *@a1 and @a2 should be the same type. tal_count(@a1) will
|
||||
* be increased by @num2.
|
||||
*
|
||||
* Example:
|
||||
* int *arr1 = tal_arrz(NULL, int, 2);
|
||||
* int arr2[2] = { 1, 3 };
|
||||
*
|
||||
* tal_expand(&arr1, arr2, 2);
|
||||
* assert(tal_count(arr1) == 4);
|
||||
* assert(arr1[2] == 1);
|
||||
* assert(arr1[3] == 3);
|
||||
*/
|
||||
#define tal_expand(a1p, a2, num2) \
|
||||
tal_talloc_expand_((void **)(a1p), (a2), sizeof**(a1p), \
|
||||
(num2) + 0*sizeof(*(a1p) == (a2)))
|
||||
|
||||
|
||||
/**
|
||||
* tal_check - set the allocation or error functions to use
|
||||
* @ctx: a tal context, or NULL.
|
||||
* @errorstr: a string to prepend calls to error_fn, or NULL.
|
||||
*
|
||||
* This sanity-checks a tal tree (unless NDEBUG is defined, in which case
|
||||
* it simply returns true). If errorstr is not null, error_fn is called
|
||||
* when a problem is found, otherwise it is not.
|
||||
*/
|
||||
#define tal_check(ctx, errorstr) \
|
||||
tal_talloc_check_((ctx), (errorstr))
|
||||
|
||||
|
||||
/* Internal support functions */
|
||||
#ifndef TAL_TALLOC_LABEL
|
||||
#ifdef CCAN_TAL_NO_LABELS
|
||||
#define TAL_LABEL(type, arr) NULL
|
||||
#else
|
||||
#ifdef CCAN_TAL_DEBUG
|
||||
#define TAL_LABEL(type, arr) \
|
||||
__FILE__ ":" stringify(__LINE__) ":" stringify(type) arr
|
||||
#else
|
||||
#define TAL_LABEL(type, arr) stringify(type) arr
|
||||
#endif /* CCAN_TAL_DEBUG */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAVE_BUILTIN_CONSTANT_P
|
||||
#define TAL_TALLOC_IS_LITERAL(str) __builtin_constant_p(str)
|
||||
#else
|
||||
#define TAL_TALLOC_IS_LITERAL(str) false
|
||||
#endif
|
||||
|
||||
#if HAVE_TYPEOF && HAVE_STATEMENT_EXPR
|
||||
/* Careful: ptr can be const foo *, ptype is foo *. Also, ptr could
|
||||
* be an array, eg "hello". */
|
||||
#define tal_talloc_typechk_(ptr, ptype) ({ __typeof__((ptr)+0) _p = (ptype)(ptr); _p; })
|
||||
#else
|
||||
#define tal_talloc_typechk_(ptr, ptype) (ptr)
|
||||
#endif
|
||||
|
||||
void *tal_talloc_(const tal_t *ctx, size_t bytes, bool clear,
|
||||
const char *label);
|
||||
void *tal_talloc_arr_(const tal_t *ctx, size_t bytes, size_t count, bool clear,
|
||||
const char *label);
|
||||
void *tal_talloc_free_(const tal_t *ctx);
|
||||
const char *tal_talloc_name_(const tal_t *ctx);
|
||||
bool tal_talloc_set_name_(tal_t *ctx, const char *name, bool literal);
|
||||
|
||||
bool tal_talloc_add_destructor_(const tal_t *ctx, void (*destroy)(void *me));
|
||||
bool tal_talloc_del_destructor_(const tal_t *ctx, void (*destroy)(void *me));
|
||||
|
||||
/* ccan/tal/str uses this, so define it. */
|
||||
#define tal_dup_(ctx, p, size, n, extra, add_count, label) \
|
||||
tal_talloc_dup_((ctx), (p), (size), (n), (extra), (label))
|
||||
void *tal_talloc_dup_(const tal_t *ctx, const void *p, size_t size,
|
||||
size_t n, size_t extra, const char *label);
|
||||
|
||||
bool tal_talloc_resize_(tal_t **ctxp, size_t size, size_t count);
|
||||
bool tal_talloc_expand_(tal_t **ctxp, const void *src, size_t size, size_t count);
|
||||
bool tal_talloc_check_(const tal_t *ctx, const char *errorstr);
|
||||
|
||||
void tal_talloc_set_backend_(void *(*alloc_fn)(size_t size),
|
||||
void *(*resize_fn)(void *, size_t size),
|
||||
void (*free_fn)(void *),
|
||||
void (*error_fn)(const char *msg));
|
||||
|
||||
#endif /* CCAN_TAL_TALLOC_H */
|
@ -1,46 +0,0 @@
|
||||
#include <ccan/tal/talloc/talloc.h>
|
||||
#include <ccan/tal/talloc/talloc.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char *parent, *c[4];
|
||||
int i;
|
||||
|
||||
plan_tests(11);
|
||||
|
||||
parent = tal(NULL, char);
|
||||
ok1(parent);
|
||||
|
||||
/* Zeroing allocations. */
|
||||
for (i = 0; i < 4; i++) {
|
||||
c[i] = talz(parent, char);
|
||||
ok1(*c[i] == '\0');
|
||||
tal_free(c[i]);
|
||||
}
|
||||
|
||||
/* Array allocation. */
|
||||
for (i = 0; i < 4; i++) {
|
||||
c[i] = tal_arr(parent, char, 4);
|
||||
strcpy(c[i], "abc");
|
||||
tal_free(c[i]);
|
||||
}
|
||||
|
||||
/* Zeroing array allocation. */
|
||||
for (i = 0; i < 4; i++) {
|
||||
c[i] = tal_arrz(parent, char, 4);
|
||||
ok1(!c[i][0] && !c[i][1] && !c[i][2] && !c[i][3]);
|
||||
strcpy(c[i], "abc");
|
||||
tal_free(c[i]);
|
||||
}
|
||||
|
||||
/* Resizing. */
|
||||
c[0] = tal_arrz(parent, char, 4);
|
||||
ok1(tal_resize(&c[0], 6));
|
||||
strcpy(c[0], "hello");
|
||||
tal_free(c[0]);
|
||||
ok1(talloc_total_blocks(parent) == 1);
|
||||
tal_free(parent);
|
||||
|
||||
return exit_status();
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
#include <ccan/tal/talloc/talloc.h>
|
||||
#include <ccan/tal/talloc/talloc.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char *p1, *p2;
|
||||
|
||||
plan_tests(12);
|
||||
|
||||
p1 = tal(NULL, char);
|
||||
ok1(p1);
|
||||
ok1(tal_count(p1) == 1);
|
||||
|
||||
p2 = tal_arr(p1, char, 1);
|
||||
ok1(p2);
|
||||
ok1(tal_count(p2) == 1);
|
||||
ok1(tal_resize(&p2, 2));
|
||||
ok1(tal_count(p2) == 2);
|
||||
ok1(tal_check(NULL, NULL));
|
||||
tal_free(p2);
|
||||
|
||||
p2 = tal_arrz(p1, char, 7);
|
||||
ok1(p2);
|
||||
ok1(tal_count(p2) == 7);
|
||||
ok1(tal_resize(&p2, 0));
|
||||
ok1(tal_count(p2) == 0);
|
||||
ok1(tal_check(NULL, NULL));
|
||||
tal_free(p2);
|
||||
tal_free(p1);
|
||||
|
||||
return exit_status();
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
#include <ccan/tal/talloc/talloc.h>
|
||||
#include <ccan/tal/talloc/talloc.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
static char *parent, *child;
|
||||
static int destroy_count;
|
||||
|
||||
/* Parent gets destroyed first. */
|
||||
static void destroy_parent(char *p)
|
||||
{
|
||||
ok1(p == parent);
|
||||
ok1(destroy_count == 0);
|
||||
/* Can still access child. */
|
||||
*child = '1';
|
||||
destroy_count++;
|
||||
}
|
||||
|
||||
static void destroy_child(char *p)
|
||||
{
|
||||
ok1(p == child);
|
||||
ok1(destroy_count == 1);
|
||||
/* Can still access parent (though destructor has been called). */
|
||||
*parent = '1';
|
||||
destroy_count++;
|
||||
}
|
||||
|
||||
static void destroy_inc(char *p)
|
||||
{
|
||||
destroy_count++;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char *child2;
|
||||
|
||||
plan_tests(18);
|
||||
|
||||
destroy_count = 0;
|
||||
parent = tal(NULL, char);
|
||||
child = tal(parent, char);
|
||||
ok1(tal_add_destructor(parent, destroy_parent));
|
||||
ok1(tal_add_destructor(child, destroy_child));
|
||||
tal_free(parent);
|
||||
ok1(destroy_count == 2);
|
||||
|
||||
destroy_count = 0;
|
||||
parent = tal(NULL, char);
|
||||
child = tal(parent, char);
|
||||
ok1(tal_add_destructor(parent, destroy_parent));
|
||||
ok1(tal_add_destructor(child, destroy_child));
|
||||
ok1(tal_del_destructor(child, destroy_child));
|
||||
tal_free(parent);
|
||||
ok1(destroy_count == 1);
|
||||
|
||||
destroy_count = 0;
|
||||
parent = tal(NULL, char);
|
||||
child = tal(parent, char);
|
||||
child2 = tal(parent, char);
|
||||
ok1(tal_add_destructor(parent, destroy_inc));
|
||||
ok1(tal_add_destructor(parent, destroy_inc));
|
||||
ok1(tal_add_destructor(child, destroy_inc));
|
||||
ok1(tal_add_destructor(child2, destroy_inc));
|
||||
tal_free(parent);
|
||||
ok1(destroy_count == 4);
|
||||
|
||||
return exit_status();
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
#include <ccan/tal/talloc/talloc.h>
|
||||
#include <ccan/tal/talloc/talloc.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int *a;
|
||||
const int arr[] = { 1, 2 };
|
||||
|
||||
plan_tests(14);
|
||||
talloc_enable_null_tracking_no_autofree();
|
||||
|
||||
a = tal_arrz(NULL, int, 1);
|
||||
ok1(a);
|
||||
|
||||
ok1(tal_expand(&a, arr, 2));
|
||||
ok1(tal_count(a) == 3);
|
||||
ok1(a[0] == 0);
|
||||
ok1(a[1] == 1);
|
||||
ok1(a[2] == 2);
|
||||
|
||||
ok1(tal_expand(&a, take(tal_arrz(NULL, int, 1)), 1));
|
||||
ok1(tal_count(a) == 4);
|
||||
ok1(a[0] == 0);
|
||||
ok1(a[1] == 1);
|
||||
ok1(a[2] == 2);
|
||||
ok1(a[3] == 0);
|
||||
ok1(talloc_total_blocks(NULL) == 2);
|
||||
ok1(talloc_total_blocks(a) == 1);
|
||||
|
||||
tal_free(a);
|
||||
|
||||
talloc_disable_null_tracking();
|
||||
return exit_status();
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
#include <ccan/tal/talloc/talloc.h>
|
||||
#include <ccan/tal/talloc/talloc.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
#include <errno.h>
|
||||
|
||||
static void destroy_errno(char *p)
|
||||
{
|
||||
errno = ENOENT;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char *p;
|
||||
|
||||
plan_tests(2);
|
||||
|
||||
p = tal(NULL, char);
|
||||
ok1(tal_add_destructor(p, destroy_errno));
|
||||
|
||||
/* Errno save/restored across free. */
|
||||
errno = EINVAL;
|
||||
tal_free(p);
|
||||
ok1(errno == EINVAL);
|
||||
|
||||
return exit_status();
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
#define CCAN_TAL_DEBUG
|
||||
#include <ccan/tal/talloc/talloc.h>
|
||||
#include <ccan/tal/talloc/talloc.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int *p;
|
||||
char name[] = "test name";
|
||||
|
||||
plan_tests(6);
|
||||
|
||||
p = tal(NULL, int);
|
||||
ok1(strcmp(tal_name(p), __FILE__ ":13:int") == 0);
|
||||
|
||||
tal_set_name(p, "some literal");
|
||||
ok1(strcmp(tal_name(p), "some literal") == 0);
|
||||
|
||||
tal_set_name(p, name);
|
||||
ok1(strcmp(tal_name(p), name) == 0);
|
||||
/* You can't reuse my pointer though! */
|
||||
ok1(tal_name(p) != name);
|
||||
|
||||
tal_set_name(p, "some other literal");
|
||||
ok1(strcmp(tal_name(p), "some other literal") == 0);
|
||||
|
||||
tal_free(p);
|
||||
|
||||
p = tal_arr(NULL, int, 2);
|
||||
ok1(strcmp(tal_name(p), __FILE__ ":29:int[]") == 0);
|
||||
tal_free(p);
|
||||
|
||||
return exit_status();
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
#define CCAN_TAL_NO_LABELS
|
||||
#include <ccan/tal/talloc/talloc.h>
|
||||
#include <ccan/tal/talloc/talloc.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int *p;
|
||||
char name[] = "test name";
|
||||
|
||||
plan_tests(5);
|
||||
|
||||
p = tal(NULL, int);
|
||||
ok1(tal_name(p) == NULL);
|
||||
|
||||
tal_set_name(p, "some literal");
|
||||
ok1(strcmp(tal_name(p), "some literal") == 0);
|
||||
|
||||
tal_set_name(p, name);
|
||||
ok1(strcmp(tal_name(p), name) == 0);
|
||||
/* You can't reuse my pointer though! */
|
||||
ok1(tal_name(p) != name);
|
||||
|
||||
tal_set_name(p, "some other literal");
|
||||
ok1(strcmp(tal_name(p), "some other literal") == 0);
|
||||
|
||||
tal_free(p);
|
||||
|
||||
return exit_status();
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
#include <ccan/tal/talloc/talloc.h>
|
||||
#include <ccan/tal/talloc/talloc.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int *p;
|
||||
char name[] = "test name";
|
||||
|
||||
plan_tests(6);
|
||||
|
||||
p = tal(NULL, int);
|
||||
ok1(strcmp(tal_name(p), "int") == 0);
|
||||
|
||||
tal_set_name(p, "some literal");
|
||||
ok1(strcmp(tal_name(p), "some literal") == 0);
|
||||
|
||||
tal_set_name(p, name);
|
||||
ok1(strcmp(tal_name(p), name) == 0);
|
||||
/* You can't reuse my pointer though! */
|
||||
ok1(tal_name(p) != name);
|
||||
|
||||
tal_set_name(p, "some other literal");
|
||||
ok1(strcmp(tal_name(p), "some other literal") == 0);
|
||||
|
||||
tal_free(p);
|
||||
|
||||
p = tal_arr(NULL, int, 2);
|
||||
ok1(strcmp(tal_name(p), "int[]") == 0);
|
||||
tal_free(p);
|
||||
|
||||
return exit_status();
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
#include <ccan/tal/talloc/talloc.h>
|
||||
#include <ccan/tal/talloc/talloc.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
static int error_count;
|
||||
|
||||
static void my_error(const char *msg)
|
||||
{
|
||||
error_count++;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
void *p;
|
||||
int *pi, *origpi;
|
||||
char *cp;
|
||||
|
||||
plan_tests(30);
|
||||
|
||||
tal_set_backend(NULL, NULL, NULL, my_error);
|
||||
talloc_enable_null_tracking_no_autofree();
|
||||
|
||||
p = tal_arr(NULL, int, (size_t)-1);
|
||||
ok1(!p);
|
||||
ok1(error_count == 1);
|
||||
|
||||
p = tal_arr(NULL, char, (size_t)-2);
|
||||
ok1(!p);
|
||||
ok1(error_count == 2);
|
||||
|
||||
/* Now try overflow cases for tal_dup. */
|
||||
error_count = 0;
|
||||
origpi = tal_arr(NULL, int, 100);
|
||||
ok1(origpi);
|
||||
ok1(error_count == 0);
|
||||
pi = tal_dup_arr(NULL, int, origpi, (size_t)-1, 0);
|
||||
ok1(!pi);
|
||||
ok1(error_count == 1);
|
||||
pi = tal_dup_arr(NULL, int, origpi, 0, (size_t)-1);
|
||||
ok1(!pi);
|
||||
ok1(error_count == 2);
|
||||
|
||||
pi = tal_dup_arr(NULL, int, origpi, (size_t)-1UL / sizeof(int),
|
||||
(size_t)-1UL / sizeof(int));
|
||||
ok1(!pi);
|
||||
ok1(error_count == 3);
|
||||
/* This will still overflow when tal_hdr is added. */
|
||||
pi = tal_dup_arr(NULL, int, origpi, (size_t)-1UL / sizeof(int) / 2,
|
||||
(size_t)-1UL / sizeof(int) / 2);
|
||||
ok1(!pi);
|
||||
ok1(error_count == 4);
|
||||
ok1(talloc_total_blocks(NULL) == 2);
|
||||
tal_free(origpi);
|
||||
|
||||
/* Now, check that with taltk() we free old one on failure. */
|
||||
origpi = tal_arr(NULL, int, 100);
|
||||
error_count = 0;
|
||||
pi = tal_dup_arr(NULL, int, take(origpi), (size_t)-1, 0);
|
||||
ok1(!pi);
|
||||
ok1(error_count == 1);
|
||||
|
||||
origpi = tal_arr(NULL, int, 100);
|
||||
error_count = 0;
|
||||
pi = tal_dup_arr(NULL, int, take(origpi), 0, (size_t)-1);
|
||||
ok1(!pi);
|
||||
ok1(error_count == 1);
|
||||
ok1(talloc_total_blocks(NULL) == 1);
|
||||
|
||||
origpi = tal_arr(NULL, int, 100);
|
||||
error_count = 0;
|
||||
pi = tal_dup_arr(NULL, int, take(origpi), (size_t)-1UL / sizeof(int),
|
||||
(size_t)-1UL / sizeof(int));
|
||||
ok1(!pi);
|
||||
ok1(error_count == 1);
|
||||
ok1(talloc_total_blocks(NULL) == 1);
|
||||
|
||||
origpi = tal_arr(NULL, int, 100);
|
||||
error_count = 0;
|
||||
/* This will still overflow when tal_hdr is added. */
|
||||
pi = tal_dup_arr(NULL, int, take(origpi), (size_t)-1UL / sizeof(int) / 2,
|
||||
(size_t)-1UL / sizeof(int) / 2);
|
||||
ok1(!pi);
|
||||
ok1(error_count == 1);
|
||||
ok1(talloc_total_blocks(NULL) == 1);
|
||||
|
||||
/* Overflow on expand addition. */
|
||||
cp = tal_arr(p, char, 100);
|
||||
ok1(!tal_expand(&cp, NULL, (size_t)-99UL));
|
||||
ok1(error_count == 2);
|
||||
tal_free(cp);
|
||||
|
||||
/* Overflow when multiplied by size */
|
||||
origpi = tal_arr(NULL, int, 100);
|
||||
ok1(!tal_expand(&origpi, NULL, (size_t)-1UL / sizeof(int)));
|
||||
ok1(error_count == 3);
|
||||
tal_free(origpi);
|
||||
|
||||
talloc_disable_null_tracking();
|
||||
return exit_status();
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
#include <ccan/tal/talloc/talloc.h>
|
||||
#include <ccan/tal/talloc/talloc.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char *p[5];
|
||||
unsigned int i;
|
||||
|
||||
plan_tests(9);
|
||||
|
||||
p[0] = tal(NULL, char);
|
||||
for (i = 1; i < 5; i++)
|
||||
p[i] = tal(p[i-1], char);
|
||||
|
||||
tal_check(NULL, "check");
|
||||
/* Steal node with no children. */
|
||||
ok1(tal_steal(p[0], p[4]) == p[4]);
|
||||
tal_check(NULL, "check");
|
||||
/* Noop steal. */
|
||||
ok1(tal_steal(p[0], p[4]) == p[4]);
|
||||
tal_check(NULL, "check");
|
||||
/* Steal with children. */
|
||||
ok1(tal_steal(p[0], p[1]) == p[1]);
|
||||
tal_check(NULL, "check");
|
||||
/* Noop steal. */
|
||||
ok1(tal_steal(p[0], p[1]) == p[1]);
|
||||
tal_check(NULL, "check");
|
||||
/* Steal from direct child. */
|
||||
ok1(tal_steal(p[0], p[2]) == p[2]);
|
||||
tal_check(NULL, "check");
|
||||
|
||||
ok1(tal_parent(p[1]) == p[0]);
|
||||
ok1(tal_parent(p[2]) == p[0]);
|
||||
ok1(tal_parent(p[3]) == p[2]);
|
||||
ok1(tal_parent(p[4]) == p[0]);
|
||||
tal_free(p[0]);
|
||||
|
||||
return exit_status();
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
#include <ccan/tal/talloc/talloc.h>
|
||||
#include <ccan/tal/talloc/talloc.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char *parent, *c;
|
||||
|
||||
plan_tests(21);
|
||||
|
||||
/* We can take NULL. */
|
||||
ok1(take(NULL) == NULL);
|
||||
ok1(is_taken(NULL));
|
||||
ok1(taken(NULL)); /* Undoes take() */
|
||||
ok1(!is_taken(NULL));
|
||||
ok1(!taken(NULL));
|
||||
|
||||
parent = tal(NULL, char);
|
||||
ok1(parent);
|
||||
|
||||
ok1(take(parent) == parent);
|
||||
ok1(is_taken(parent));
|
||||
ok1(taken(parent)); /* Undoes take() */
|
||||
ok1(!is_taken(parent));
|
||||
ok1(!taken(parent));
|
||||
|
||||
c = tal(parent, char);
|
||||
*c = 'h';
|
||||
c = tal_dup(parent, char, take(c));
|
||||
ok1(c[0] == 'h');
|
||||
ok1(tal_parent(c) == parent);
|
||||
|
||||
c = tal_dup_arr(parent, char, take(c), 1, 2);
|
||||
ok1(c[0] == 'h');
|
||||
strcpy(c, "hi");
|
||||
ok1(tal_parent(c) == parent);
|
||||
|
||||
/* dup must reparent child. */
|
||||
c = tal_dup(NULL, char, take(c));
|
||||
ok1(c[0] == 'h');
|
||||
ok1(tal_parent(c) == NULL);
|
||||
|
||||
/* No leftover allocations. */
|
||||
tal_free(c);
|
||||
ok1(talloc_total_blocks(parent) == 1);
|
||||
|
||||
tal_free(parent);
|
||||
ok1(!taken_any());
|
||||
|
||||
/* NULL pass-through. */
|
||||
c = NULL;
|
||||
ok1(tal_dup_arr(NULL, char, take(c), 5, 5) == NULL);
|
||||
ok1(!taken_any());
|
||||
|
||||
return exit_status();
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
#include <ccan/tal/talloc/talloc.h>
|
||||
#include <ccan/tal/talloc/talloc.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char *parent, *c[4];
|
||||
int i, j;
|
||||
|
||||
plan_tests(9);
|
||||
|
||||
/* tal_free(NULL) works. */
|
||||
ok1(tal_free(NULL) == NULL);
|
||||
|
||||
parent = tal(NULL, char);
|
||||
ok1(parent);
|
||||
ok1(tal_parent(parent) == NULL);
|
||||
ok1(tal_parent(NULL) == NULL);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
c[i] = tal(parent, char);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
ok1(tal_parent(c[i]) == parent);
|
||||
|
||||
/* Free parent. */
|
||||
ok1(tal_free(parent) == NULL);
|
||||
|
||||
parent = tal(NULL, char);
|
||||
|
||||
/* Test freeing in every order */
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++)
|
||||
c[j] = tal(parent, char);
|
||||
|
||||
tal_free(c[i]);
|
||||
tal_free(c[(i+1) % 4]);
|
||||
tal_free(c[(i+2) % 4]);
|
||||
tal_free(c[(i+3) % 4]);
|
||||
}
|
||||
tal_free(parent);
|
||||
|
||||
return exit_status();
|
||||
}
|
Loading…
Reference in New Issue
Block a user