mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
Clean up extra ccan dirs.
Turns out that CCAN's create-ccan-tree has a bug with submodules. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
376e5bb584
commit
456a43c3b4
@ -1 +0,0 @@
|
||||
../../../licenses/CC0
|
@ -1,39 +0,0 @@
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* str/hex - hex-to-string conversions and vice-versa
|
||||
*
|
||||
* This code contains simple routines for hexidecimal strings.
|
||||
*
|
||||
* License: CC0 (Public domain)
|
||||
* Author: Rusty Russell <rusty@rustcorp.com.au>
|
||||
*
|
||||
* Example:
|
||||
* int main(int argc, char *argv[])
|
||||
* {
|
||||
* int i;
|
||||
*
|
||||
* for (i = 1; i < argc; i++) {
|
||||
* char str[hex_str_size(strlen(argv[i]))];
|
||||
*
|
||||
* hex_encode(str, sizeof(str), argv[i], strlen(argv[i]));
|
||||
* printf("%s ", str);
|
||||
* }
|
||||
* printf("\n");
|
||||
* return 0;
|
||||
* }
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/* Expect exactly one argument */
|
||||
if (argc != 2)
|
||||
return 1;
|
||||
|
||||
if (strcmp(argv[1], "depends") == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
/* CC0 license (public domain) - see LICENSE file for details */
|
||||
#include <ccan/str/hex/hex.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static bool char_to_hex(unsigned char *val, char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9') {
|
||||
*val = c - '0';
|
||||
return true;
|
||||
}
|
||||
if (c >= 'a' && c <= 'f') {
|
||||
*val = c - 'a' + 10;
|
||||
return true;
|
||||
}
|
||||
if (c >= 'A' && c <= 'F') {
|
||||
*val = c - 'A' + 10;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool hex_decode(const char *str, size_t slen, void *buf, size_t bufsize)
|
||||
{
|
||||
unsigned char v1, v2;
|
||||
unsigned char *p = buf;
|
||||
|
||||
while (slen > 1) {
|
||||
if (!char_to_hex(&v1, str[0]) || !char_to_hex(&v2, str[1]))
|
||||
return false;
|
||||
if (!bufsize)
|
||||
return false;
|
||||
*(p++) = (v1 << 4) | v2;
|
||||
str += 2;
|
||||
slen -= 2;
|
||||
bufsize--;
|
||||
}
|
||||
return slen == 0 && bufsize == 0;
|
||||
}
|
||||
|
||||
static char hexchar(unsigned int val)
|
||||
{
|
||||
if (val < 10)
|
||||
return '0' + val;
|
||||
if (val < 16)
|
||||
return 'a' + val - 10;
|
||||
abort();
|
||||
}
|
||||
|
||||
bool hex_encode(const void *buf, size_t bufsize, char *dest, size_t destsize)
|
||||
{
|
||||
size_t used = 0;
|
||||
|
||||
if (destsize < 1)
|
||||
return false;
|
||||
|
||||
while (used < bufsize) {
|
||||
unsigned int c = ((const unsigned char *)buf)[used];
|
||||
if (destsize < 3)
|
||||
return false;
|
||||
*(dest++) = hexchar(c >> 4);
|
||||
*(dest++) = hexchar(c & 0xF);
|
||||
used++;
|
||||
destsize -= 2;
|
||||
}
|
||||
*dest = '\0';
|
||||
|
||||
return used + 1;
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
/* CC0 (Public domain) - see LICENSE file for details */
|
||||
#ifndef CCAN_HEX_H
|
||||
#define CCAN_HEX_H
|
||||
#include "config.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* hex_decode - Unpack a hex string.
|
||||
* @str: the hexidecimal string
|
||||
* @slen: the length of @str
|
||||
* @buf: the buffer to write the data into
|
||||
* @bufsize: the length of @buf
|
||||
*
|
||||
* Returns false if there are any characters which aren't 0-9, a-f or A-F,
|
||||
* of the string wasn't the right length for @bufsize.
|
||||
*
|
||||
* Example:
|
||||
* unsigned char data[20];
|
||||
*
|
||||
* if (!hex_decode(argv[1], strlen(argv[1]), data, 20))
|
||||
* printf("String is malformed!\n");
|
||||
*/
|
||||
bool hex_decode(const char *str, size_t slen, void *buf, size_t bufsize);
|
||||
|
||||
/**
|
||||
* hex_encode - Create a nul-terminated hex string
|
||||
* @buf: the buffer to read the data from
|
||||
* @bufsize: the length of @buf
|
||||
* @dest: the string to fill
|
||||
* @destsize: the max size of the string
|
||||
*
|
||||
* Returns true if the string, including terminator, fit in @destsize;
|
||||
*
|
||||
* Example:
|
||||
* unsigned char buf[] = { 0x1F, 0x2F };
|
||||
* char str[5];
|
||||
*
|
||||
* if (!hex_encode(buf, sizeof(buf), str, sizeof(str)))
|
||||
* abort();
|
||||
*/
|
||||
bool hex_encode(const void *buf, size_t bufsize, char *dest, size_t destsize);
|
||||
|
||||
/**
|
||||
* hex_str_size - Calculate how big a nul-terminated hex string is
|
||||
* @bytes: bytes of data to represent
|
||||
*
|
||||
* Example:
|
||||
* unsigned char buf[] = { 0x1F, 0x2F };
|
||||
* char str[hex_str_size(sizeof(buf))];
|
||||
*
|
||||
* hex_encode(buf, sizeof(buf), str, sizeof(str));
|
||||
*/
|
||||
static inline size_t hex_str_size(size_t bytes)
|
||||
{
|
||||
return 2 * bytes + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* hex_data_size - Calculate how many bytes of data in a hex string
|
||||
* @strlen: the length of the string (with or without NUL)
|
||||
*
|
||||
* Example:
|
||||
* const char str[] = "1F2F";
|
||||
* unsigned char buf[hex_data_size(sizeof(str))];
|
||||
*
|
||||
* hex_decode(str, strlen(str), buf, sizeof(buf));
|
||||
*/
|
||||
static inline size_t hex_data_size(size_t strlen)
|
||||
{
|
||||
return strlen / 2;
|
||||
}
|
||||
#endif /* PETTYCOIN_HEX_H */
|
@ -1,42 +0,0 @@
|
||||
#include <ccan/str/hex/hex.h>
|
||||
/* Include the C files directly. */
|
||||
#include <ccan/str/hex/hex.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
const char teststr[] = "0123456789abcdefABCDEF";
|
||||
const char bad_teststr[] = "0123456789abcdefABCDEF1O";
|
||||
const unsigned char testdata[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab,
|
||||
0xcd, 0xef, 0xAB, 0xCD, 0xEF };
|
||||
unsigned char data[11];
|
||||
char str[23];
|
||||
size_t i;
|
||||
|
||||
plan_tests(10 + sizeof(str));
|
||||
|
||||
ok1(hex_str_size(sizeof(testdata)) == sizeof(teststr));
|
||||
/* This gives right result with or without nul included */
|
||||
ok1(hex_data_size(strlen(teststr)) == sizeof(testdata));
|
||||
ok1(hex_data_size(sizeof(teststr)) == sizeof(testdata));
|
||||
|
||||
ok1(hex_decode(teststr, strlen(teststr), data, sizeof(data)));
|
||||
ok1(memcmp(data, testdata, sizeof(testdata)) == 0);
|
||||
ok1(hex_encode(testdata, sizeof(testdata), str, sizeof(str)));
|
||||
ok1(strcmp(str, "0123456789abcdefabcdef") == 0);
|
||||
|
||||
/* Bad char */
|
||||
ok1(!hex_decode(bad_teststr, strlen(bad_teststr), data, sizeof(data)));
|
||||
/* Bad hex string len */
|
||||
ok1(!hex_decode(teststr, strlen(teststr) - 1, data, sizeof(data)));
|
||||
/* Bad buffer len */
|
||||
ok1(!hex_decode(teststr, strlen(teststr), data, sizeof(data) - 1));
|
||||
|
||||
/* Bad deststring size. */
|
||||
for (i = 1; i <= sizeof(str); i++)
|
||||
ok1(!hex_encode(testdata, sizeof(testdata), str, sizeof(str)-i));
|
||||
|
||||
/* This exits depending on whether all tests passed */
|
||||
return exit_status();
|
||||
}
|
@ -1 +0,0 @@
|
||||
../../../licenses/LGPL-2.1
|
@ -1,56 +0,0 @@
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* tal/grab_file - file helper routines
|
||||
*
|
||||
* This contains simple functions for getting the contents of a file.
|
||||
*
|
||||
* Example:
|
||||
* #include <err.h>
|
||||
* #include <stdio.h>
|
||||
* #include <string.h>
|
||||
* #include <ccan/tal/grab_file/grab_file.h>
|
||||
* #include <ccan/tal/tal.h> // for tal_free
|
||||
*
|
||||
* int main(int argc, char *argv[])
|
||||
* {
|
||||
* char *file;
|
||||
*
|
||||
* file = grab_file(NULL, argv[1]);
|
||||
* if (!file)
|
||||
* err(1, "Could not read file %s", argv[1]);
|
||||
* if (strlen(file)+1 != tal_count(file))
|
||||
* printf("File contains NUL characters\n");
|
||||
* else if (tal_count(file) == 1)
|
||||
* printf("File contains nothing\n");
|
||||
* else if (strchr(file, '\n'))
|
||||
* printf("File contains multiple lines\n");
|
||||
* else
|
||||
* printf("File contains one line\n");
|
||||
* tal_free(file);
|
||||
*
|
||||
* return 0;
|
||||
* }
|
||||
*
|
||||
* License: LGPL (v2.1 or any later version)
|
||||
* 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/tal\n");
|
||||
printf("ccan/noerr\n");
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(argv[1], "testdepends") == 0) {
|
||||
printf("ccan/tal/str\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/* Licensed under LGPLv2+ - see LICENSE file for details */
|
||||
#include "grab_file.h"
|
||||
#include <ccan/tal/tal.h>
|
||||
#include <ccan/noerr/noerr.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
void *grab_fd(const void *ctx, int fd)
|
||||
{
|
||||
int ret;
|
||||
size_t max, size;
|
||||
char *buffer;
|
||||
struct stat st;
|
||||
|
||||
size = 0;
|
||||
|
||||
if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode))
|
||||
max = st.st_size;
|
||||
else
|
||||
max = 16384;
|
||||
|
||||
buffer = tal_arr(ctx, char, max+1);
|
||||
while ((ret = read(fd, buffer + size, max - size)) > 0) {
|
||||
size += ret;
|
||||
if (size == max) {
|
||||
size_t extra = max;
|
||||
if (extra > 1024 * 1024)
|
||||
extra = 1024 * 1024;
|
||||
|
||||
if (!tal_resize(&buffer, max+extra+1))
|
||||
return NULL;
|
||||
|
||||
max += extra;
|
||||
}
|
||||
}
|
||||
if (ret < 0)
|
||||
buffer = tal_free(buffer);
|
||||
else {
|
||||
buffer[size] = '\0';
|
||||
tal_resize(&buffer, size+1);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void *grab_file(const void *ctx, const char *filename)
|
||||
{
|
||||
int fd;
|
||||
char *buffer;
|
||||
|
||||
if (!filename)
|
||||
fd = dup(STDIN_FILENO);
|
||||
else
|
||||
fd = open(filename, O_RDONLY, 0);
|
||||
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
|
||||
buffer = grab_fd(ctx, fd);
|
||||
close_noerr(fd);
|
||||
return buffer;
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
/* Licensed under LGPLv2+ - see LICENSE file for details */
|
||||
#ifndef CCAN_TAL_GRAB_FILE_H
|
||||
#define CCAN_TAL_GRAB_FILE_H
|
||||
#include <stdio.h> // For size_t
|
||||
|
||||
/**
|
||||
* grab_fd - read all of a file descriptor into memory
|
||||
* @ctx: the context to tallocate from (often NULL)
|
||||
* @fd: the file descriptor to read from
|
||||
*
|
||||
* This function reads from the given file descriptor until no more
|
||||
* input is available. The content is talloced off @ctx, and the
|
||||
* tal_count() is the size in bytes plus one: for convenience, the
|
||||
* byte after the end of the content will always be NUL.
|
||||
*
|
||||
* Example:
|
||||
* #include <ccan/tal/str/str.h>
|
||||
* #include <ccan/tal/tal.h>
|
||||
* ...
|
||||
* // Return all of standard input, as lines.
|
||||
* static char **read_stdin_as_lines(void)
|
||||
* {
|
||||
* char **lines, *all;
|
||||
*
|
||||
* all = grab_fd(NULL, 0);
|
||||
* if (!all)
|
||||
* return NULL;
|
||||
* lines = tal_strsplit(NULL, all, "\n", STR_EMPTY_OK);
|
||||
* tal_free(all);
|
||||
* return lines;
|
||||
* }
|
||||
*/
|
||||
void *grab_fd(const void *ctx, int fd);
|
||||
|
||||
/**
|
||||
* grab_file - read all of a file (or stdin) into memory
|
||||
* @ctx: the context to tallocate from (often NULL)
|
||||
* @filename: the file to read (NULL for stdin)
|
||||
*
|
||||
* This function reads from the given file until no more input is
|
||||
* available. The content is talloced off @ctx, and the tal_count()
|
||||
* is the size in bytes plus one: for convenience, the byte after the
|
||||
* end of the content will always be NUL.
|
||||
*
|
||||
* Example:
|
||||
* // Return all of a given file, as lines.
|
||||
* static char **read_file_as_lines(const char *filename)
|
||||
* {
|
||||
* char **lines, *all;
|
||||
*
|
||||
* all = grab_file(NULL, filename);
|
||||
* if (!all)
|
||||
* return NULL;
|
||||
* lines = tal_strsplit(NULL, all, "\n", STR_EMPTY_OK);
|
||||
* tal_free(all);
|
||||
* return lines;
|
||||
* }
|
||||
*/
|
||||
void *grab_file(const void *ctx, const char *filename);
|
||||
#endif /* CCAN_TAL_GRAB_FILE_H */
|
@ -1,37 +0,0 @@
|
||||
/* This is test for grab_file() function
|
||||
*/
|
||||
#include <ccan/tal/grab_file/grab_file.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <err.h>
|
||||
#include <sys/stat.h>
|
||||
#include <ccan/tal/grab_file/grab_file.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
unsigned int i;
|
||||
char **split, *str;
|
||||
int length;
|
||||
struct stat st;
|
||||
|
||||
str = grab_file(NULL, "test/run-grab.c");
|
||||
split = tal_strsplit(str, str, "\n", STR_EMPTY_OK);
|
||||
length = strlen(split[0]);
|
||||
ok1(!strcmp(split[0], "/* This is test for grab_file() function"));
|
||||
for (i = 1; split[i]; i++)
|
||||
length += strlen(split[i]);
|
||||
ok1(!strcmp(split[i-1], "/* End of grab_file() test */"));
|
||||
if (stat("test/run-grab.c", &st) != 0)
|
||||
/* FIXME: ditto */
|
||||
if (stat("ccan/tal/grab_file/test/run-grab.c", &st) != 0)
|
||||
err(1, "Could not stat self");
|
||||
ok1(st.st_size == length + i);
|
||||
tal_free(str);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* End of grab_file() test */
|
@ -1 +0,0 @@
|
||||
../../../licenses/BSD-MIT
|
@ -1,57 +0,0 @@
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* tal/str - string helper routines which use tal
|
||||
*
|
||||
* This is a grab bag of functions for string operations, designed to enhance
|
||||
* the standard string.h; these are separated from the non-tal-needing
|
||||
* string utilities in "str.h".
|
||||
*
|
||||
* Example:
|
||||
* #include <ccan/tal/str/str.h>
|
||||
* #include <ccan/tal/grab_file/grab_file.h>
|
||||
* #include <err.h>
|
||||
*
|
||||
* // Dumb demo program to double-linespace a file.
|
||||
* int main(int argc, char *argv[])
|
||||
* {
|
||||
* char *textfile;
|
||||
* char **lines;
|
||||
*
|
||||
* // Grab lines in file.
|
||||
* textfile = grab_file(NULL, argv[1]);
|
||||
* if (!textfile)
|
||||
* err(1, "Failed reading %s", argv[1]);
|
||||
* lines = tal_strsplit(textfile, textfile, "\n", STR_EMPTY_OK);
|
||||
*
|
||||
* // Join them back together with two linefeeds.
|
||||
* printf("%s", tal_strjoin(textfile, lines, "\n\n", STR_TRAIL));
|
||||
*
|
||||
* // Free everything, just because we can.
|
||||
* tal_free(textfile);
|
||||
* 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/str\n");
|
||||
#ifdef TAL_USE_TALLOC
|
||||
printf("ccan/tal/talloc\n");
|
||||
#else
|
||||
printf("ccan/tal\n");
|
||||
#endif
|
||||
printf("ccan/take\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
@ -1,312 +0,0 @@
|
||||
/* Licensed under BSD-MIT - see LICENSE file for details */
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include "str.h"
|
||||
#include <sys/types.h>
|
||||
#include <regex.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <ccan/str/str.h>
|
||||
#include <ccan/take/take.h>
|
||||
|
||||
char *tal_strdup(const tal_t *ctx, const char *p)
|
||||
{
|
||||
/* We have to let through NULL for take(). */
|
||||
return tal_dup_(ctx, p, 1, p ? strlen(p) + 1: 1, 0, false,
|
||||
TAL_LABEL(char, "[]"));
|
||||
}
|
||||
|
||||
char *tal_strndup(const tal_t *ctx, const char *p, size_t n)
|
||||
{
|
||||
size_t len;
|
||||
char *ret;
|
||||
|
||||
/* We have to let through NULL for take(). */
|
||||
if (likely(p)) {
|
||||
len = strlen(p);
|
||||
if (len > n)
|
||||
len = n;
|
||||
} else
|
||||
len = n;
|
||||
|
||||
ret = tal_dup_(ctx, p, 1, len, 1, false, TAL_LABEL(char, "[]"));
|
||||
if (ret)
|
||||
ret[len] = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *tal_fmt(const tal_t *ctx, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *ret;
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = tal_vfmt(ctx, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool do_vfmt(char **buf, size_t off, const char *fmt, va_list ap)
|
||||
{
|
||||
/* A decent guess to start. */
|
||||
size_t max = strlen(fmt) * 2;
|
||||
bool ok;
|
||||
|
||||
for (;;) {
|
||||
va_list ap2;
|
||||
int ret;
|
||||
|
||||
if (!tal_resize(buf, off + max)) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
||||
va_copy(ap2, ap);
|
||||
ret = vsnprintf(*buf + off, max, fmt, ap2);
|
||||
va_end(ap2);
|
||||
|
||||
if (ret < max) {
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
max *= 2;
|
||||
}
|
||||
|
||||
if (taken(fmt))
|
||||
tal_free(fmt);
|
||||
return ok;
|
||||
}
|
||||
|
||||
char *tal_vfmt(const tal_t *ctx, const char *fmt, va_list ap)
|
||||
{
|
||||
char *buf;
|
||||
|
||||
if (!fmt && taken(fmt))
|
||||
return NULL;
|
||||
|
||||
/* A decent guess to start. */
|
||||
buf = tal_arr(ctx, char, strlen(fmt) * 2);
|
||||
if (!do_vfmt(&buf, 0, fmt, ap))
|
||||
buf = tal_free(buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
bool tal_append_vfmt(char **baseptr, const char *fmt, va_list ap)
|
||||
{
|
||||
if (!fmt && taken(fmt))
|
||||
return false;
|
||||
|
||||
return do_vfmt(baseptr, strlen(*baseptr), fmt, ap);
|
||||
}
|
||||
|
||||
bool tal_append_fmt(char **baseptr, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
bool ret;
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = tal_append_vfmt(baseptr, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *tal_strcat(const tal_t *ctx, const char *s1, const char *s2)
|
||||
{
|
||||
size_t len1, len2;
|
||||
char *ret;
|
||||
|
||||
if (unlikely(!s2) && taken(s2)) {
|
||||
if (taken(s1))
|
||||
tal_free(s1);
|
||||
return NULL;
|
||||
}
|
||||
/* We have to let through NULL for take(). */
|
||||
len1 = s1 ? strlen(s1) : 0;
|
||||
len2 = strlen(s2);
|
||||
|
||||
/* We use tal_dup_ here to avoid attaching a length property. */
|
||||
ret = tal_dup_(ctx, s1, 1, len1, len2 + 1, false,
|
||||
TAL_LABEL(char, "[]"));
|
||||
if (likely(ret))
|
||||
memcpy(ret + len1, s2, len2 + 1);
|
||||
|
||||
if (taken(s2))
|
||||
tal_free(s2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char **tal_strsplit(const tal_t *ctx,
|
||||
const char *string, const char *delims, enum strsplit flags)
|
||||
{
|
||||
char **parts, *str;
|
||||
size_t max = 64, num = 0;
|
||||
|
||||
parts = tal_arr(ctx, char *, max + 1);
|
||||
if (unlikely(!parts)) {
|
||||
if (taken(string))
|
||||
tal_free(string);
|
||||
if (taken(delims))
|
||||
tal_free(delims);
|
||||
return NULL;
|
||||
}
|
||||
str = tal_strdup(parts, string);
|
||||
if (unlikely(!str))
|
||||
goto fail;
|
||||
if (unlikely(!delims) && is_taken(delims))
|
||||
goto fail;
|
||||
|
||||
if (flags == STR_NO_EMPTY)
|
||||
str += strspn(str, delims);
|
||||
|
||||
while (*str != '\0') {
|
||||
size_t len = strcspn(str, delims), dlen;
|
||||
|
||||
parts[num] = str;
|
||||
dlen = strspn(str + len, delims);
|
||||
parts[num][len] = '\0';
|
||||
if (flags == STR_EMPTY_OK && dlen)
|
||||
dlen = 1;
|
||||
str += len + dlen;
|
||||
if (++num == max && !tal_resize(&parts, max*=2 + 1))
|
||||
goto fail;
|
||||
}
|
||||
parts[num] = NULL;
|
||||
|
||||
/* Ensure that tal_count() is correct. */
|
||||
if (unlikely(!tal_resize(&parts, num+1)))
|
||||
goto fail;
|
||||
|
||||
if (taken(delims))
|
||||
tal_free(delims);
|
||||
return parts;
|
||||
|
||||
fail:
|
||||
tal_free(parts);
|
||||
if (taken(delims))
|
||||
tal_free(delims);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *tal_strjoin(const tal_t *ctx,
|
||||
char *strings[], const char *delim, enum strjoin flags)
|
||||
{
|
||||
unsigned int i;
|
||||
char *ret = NULL;
|
||||
size_t totlen = 0, dlen;
|
||||
|
||||
if (unlikely(!strings) && is_taken(strings))
|
||||
goto fail;
|
||||
|
||||
if (unlikely(!delim) && is_taken(delim))
|
||||
goto fail;
|
||||
|
||||
dlen = strlen(delim);
|
||||
ret = tal_arr(ctx, char, dlen*2+1);
|
||||
if (!ret)
|
||||
goto fail;
|
||||
|
||||
ret[0] = '\0';
|
||||
for (i = 0; strings[i]; i++) {
|
||||
size_t len = strlen(strings[i]);
|
||||
|
||||
if (flags == STR_NO_TRAIL && !strings[i+1])
|
||||
dlen = 0;
|
||||
if (!tal_resize(&ret, totlen + len + dlen + 1))
|
||||
goto fail;
|
||||
memcpy(ret + totlen, strings[i], len);
|
||||
totlen += len;
|
||||
memcpy(ret + totlen, delim, dlen);
|
||||
totlen += dlen;
|
||||
}
|
||||
ret[totlen] = '\0';
|
||||
out:
|
||||
if (taken(strings))
|
||||
tal_free(strings);
|
||||
if (taken(delim))
|
||||
tal_free(delim);
|
||||
return ret;
|
||||
fail:
|
||||
ret = tal_free(ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
static size_t count_open_braces(const char *string)
|
||||
{
|
||||
#if 1
|
||||
size_t num = 0, esc = 0;
|
||||
|
||||
while (*string) {
|
||||
if (*string == '\\')
|
||||
esc++;
|
||||
else {
|
||||
/* An odd number of \ means it's escaped. */
|
||||
if (*string == '(' && (esc & 1) == 0)
|
||||
num++;
|
||||
esc = 0;
|
||||
}
|
||||
string++;
|
||||
}
|
||||
return num;
|
||||
#else
|
||||
return strcount(string, "(");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool tal_strreg(const tal_t *ctx, const char *string, const char *regex, ...)
|
||||
{
|
||||
size_t nmatch = 1 + count_open_braces(regex);
|
||||
regmatch_t matches[nmatch];
|
||||
regex_t r;
|
||||
bool ret = false;
|
||||
unsigned int i;
|
||||
va_list ap;
|
||||
|
||||
if (unlikely(!regex) && is_taken(regex))
|
||||
goto fail_no_re;
|
||||
|
||||
if (regcomp(&r, regex, REG_EXTENDED) != 0)
|
||||
goto fail_no_re;
|
||||
|
||||
if (unlikely(!string) && is_taken(string))
|
||||
goto fail;
|
||||
|
||||
if (regexec(&r, string, nmatch, matches, 0) != 0)
|
||||
goto fail;
|
||||
|
||||
ret = true;
|
||||
va_start(ap, regex);
|
||||
for (i = 1; i < nmatch; i++) {
|
||||
char **arg = va_arg(ap, char **);
|
||||
if (arg) {
|
||||
/* eg. ([a-z])? can give "no match". */
|
||||
if (matches[i].rm_so == -1)
|
||||
*arg = NULL;
|
||||
else {
|
||||
*arg = tal_strndup(ctx,
|
||||
string + matches[i].rm_so,
|
||||
matches[i].rm_eo
|
||||
- matches[i].rm_so);
|
||||
/* FIXME: If we fail, we set some and leak! */
|
||||
if (!*arg) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
fail:
|
||||
regfree(&r);
|
||||
fail_no_re:
|
||||
if (taken(regex))
|
||||
tal_free(regex);
|
||||
if (taken(string))
|
||||
tal_free(string);
|
||||
return ret;
|
||||
}
|
@ -1,186 +0,0 @@
|
||||
/* Licensed under BSD-MIT - see LICENSE file for details */
|
||||
#ifndef CCAN_STR_TAL_H
|
||||
#define CCAN_STR_TAL_H
|
||||
#ifdef TAL_USE_TALLOC
|
||||
#include <ccan/tal/talloc/talloc.h>
|
||||
#else
|
||||
#include <ccan/tal/tal.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/**
|
||||
* tal_strdup - duplicate a string
|
||||
* @ctx: NULL, or tal allocated object to be parent.
|
||||
* @p: the string to copy (can be take()).
|
||||
*/
|
||||
char *tal_strdup(const tal_t *ctx, const char *p);
|
||||
|
||||
/**
|
||||
* tal_strndup - duplicate a limited amount of a string.
|
||||
* @ctx: NULL, or tal allocated object to be parent.
|
||||
* @p: the string to copy (can be take()).
|
||||
* @n: the maximum length to copy.
|
||||
*
|
||||
* Always gives a nul-terminated string, with strlen() <= @n.
|
||||
*/
|
||||
char *tal_strndup(const tal_t *ctx, const char *p, size_t n);
|
||||
|
||||
/**
|
||||
* tal_fmt - allocate a formatted string
|
||||
* @ctx: NULL, or tal allocated object to be parent.
|
||||
* @fmt: the printf-style format (can be take()).
|
||||
*/
|
||||
char *tal_fmt(const tal_t *ctx, const char *fmt, ...) PRINTF_FMT(2,3);
|
||||
|
||||
/**
|
||||
* tal_vfmt - allocate a formatted string (va_list version)
|
||||
* @ctx: NULL, or tal allocated object to be parent.
|
||||
* @fmt: the printf-style format (can be take()).
|
||||
* @va: the va_list containing the format args.
|
||||
*/
|
||||
char *tal_vfmt(const tal_t *ctx, const char *fmt, va_list ap)
|
||||
PRINTF_FMT(2,0);
|
||||
|
||||
/**
|
||||
* tal_append_fmt - append a formatted string to a talloc string.
|
||||
* @baseptr: a pointer to the tal string to be appended to.
|
||||
* @fmt: the printf-style format (can be take()).
|
||||
*
|
||||
* Returns false on allocation failure.
|
||||
*/
|
||||
bool tal_append_fmt(char **baseptr, const char *fmt, ...) PRINTF_FMT(2,3);
|
||||
|
||||
/**
|
||||
* tal_append_vfmt - append a formatted string to a talloc string (va_list)
|
||||
* @baseptr: a pointer to the tal string to be appended to.
|
||||
* @fmt: the printf-style format (can be take()).
|
||||
* @va: the va_list containing the format args.
|
||||
*
|
||||
* Returns false on allocation failure.
|
||||
*/
|
||||
bool tal_append_vfmt(char **baseptr, const char *fmt, va_list ap);
|
||||
|
||||
/**
|
||||
* tal_strcat - join two strings together
|
||||
* @ctx: NULL, or tal allocated object to be parent.
|
||||
* @s1: the first string (can be take()).
|
||||
* @s2: the second string (can be take()).
|
||||
*/
|
||||
char *tal_strcat(const tal_t *ctx, const char *s1, const char *s2);
|
||||
|
||||
enum strsplit {
|
||||
STR_EMPTY_OK,
|
||||
STR_NO_EMPTY
|
||||
};
|
||||
|
||||
/**
|
||||
* tal_strsplit - Split string into an array of substrings
|
||||
* @ctx: the context to tal from (often NULL).
|
||||
* @string: the string to split (can be take()).
|
||||
* @delims: delimiters where lines should be split (can be take()).
|
||||
* @flags: whether to include empty substrings.
|
||||
*
|
||||
* This function splits a single string into multiple strings.
|
||||
*
|
||||
* If @string is take(), the returned array will point into the
|
||||
* mangled @string.
|
||||
*
|
||||
* Multiple delimiters result in empty substrings. By definition, no
|
||||
* delimiters will appear in the substrings.
|
||||
*
|
||||
* The final char * in the array will be NULL, and tal_count() will
|
||||
* return the number of elements plus 1 (for that NULL).
|
||||
*
|
||||
* Example:
|
||||
* #include <ccan/tal/str/str.h>
|
||||
* ...
|
||||
* static unsigned int count_long_lines(const char *string)
|
||||
* {
|
||||
* char **lines;
|
||||
* unsigned int i, long_lines = 0;
|
||||
*
|
||||
* // Can only fail on out-of-memory.
|
||||
* lines = tal_strsplit(NULL, string, "\n", STR_NO_EMPTY);
|
||||
* for (i = 0; lines[i] != NULL; i++)
|
||||
* if (strlen(lines[i]) > 80)
|
||||
* long_lines++;
|
||||
* tal_free(lines);
|
||||
* return long_lines;
|
||||
* }
|
||||
*/
|
||||
char **tal_strsplit(const tal_t *ctx,
|
||||
const char *string, const char *delims, enum strsplit flag);
|
||||
|
||||
enum strjoin {
|
||||
STR_TRAIL,
|
||||
STR_NO_TRAIL
|
||||
};
|
||||
|
||||
/**
|
||||
* tal_strjoin - Join an array of substrings into one long string
|
||||
* @ctx: the context to tal from (often NULL).
|
||||
* @strings: the NULL-terminated array of strings to join (can be take())
|
||||
* @delim: the delimiter to insert between the strings (can be take())
|
||||
* @flags: whether to add a delimieter to the end
|
||||
*
|
||||
* This function joins an array of strings into a single string. The
|
||||
* return value is allocated using tal. Each string in @strings is
|
||||
* followed by a copy of @delim.
|
||||
*
|
||||
* Example:
|
||||
* // Append the string "--EOL" to each line.
|
||||
* static char *append_to_all_lines(const char *string)
|
||||
* {
|
||||
* char **lines, *ret;
|
||||
*
|
||||
* lines = tal_strsplit(NULL, string, "\n", STR_EMPTY_OK);
|
||||
* ret = tal_strjoin(NULL, lines, "-- EOL\n", STR_TRAIL);
|
||||
* tal_free(lines);
|
||||
* return ret;
|
||||
* }
|
||||
*/
|
||||
char *tal_strjoin(const void *ctx, char *strings[], const char *delim,
|
||||
enum strjoin flags);
|
||||
|
||||
/**
|
||||
* tal_strreg - match/extract from a string via (extended) regular expressions.
|
||||
* @ctx: the context to tal from (often NULL)
|
||||
* @string: the string to try to match (can be take())
|
||||
* @regex: the regular expression to match (can be take())
|
||||
* ...: pointers to strings to allocate for subexpressions.
|
||||
*
|
||||
* Returns true if we matched, in which case any parenthesized
|
||||
* expressions in @regex are allocated and placed in the char **
|
||||
* arguments following @regex. NULL arguments mean the match is not
|
||||
* saved. The order of the strings is the order
|
||||
* of opening braces in the expression: in the case of repeated
|
||||
* expressions (eg "([a-z])*") the last one is saved, in the case of
|
||||
* non-existent matches (eg "([a-z]*)?") the pointer is set to NULL.
|
||||
*
|
||||
* Allocation failures or malformed regular expressions return false.
|
||||
*
|
||||
* See Also:
|
||||
* regcomp(3), regex(3).
|
||||
*
|
||||
* Example:
|
||||
* // Given 'My name is Rusty' outputs 'Hello Rusty!'
|
||||
* // Given 'my first name is Rusty Russell' outputs 'Hello Rusty Russell!'
|
||||
* // Given 'My name isnt Rusty Russell' outputs 'Hello there!'
|
||||
* int main(int argc, char *argv[])
|
||||
* {
|
||||
* char *person, *input;
|
||||
*
|
||||
* // Join args and trim trailing space.
|
||||
* input = tal_strjoin(NULL, argv+1, " ", STR_NO_TRAIL);
|
||||
* if (tal_strreg(NULL, input,
|
||||
* "[Mm]y (first )?name is ([A-Za-z ]+)",
|
||||
* NULL, &person))
|
||||
* printf("Hello %s!\n", person);
|
||||
* else
|
||||
* printf("Hello there!\n");
|
||||
* return 0;
|
||||
* }
|
||||
*/
|
||||
bool tal_strreg(const void *ctx, const char *string, const char *regex, ...);
|
||||
#endif /* CCAN_STR_TAL_H */
|
@ -1,22 +0,0 @@
|
||||
/* tal/talloc can't implement tal_first/tal_next. */
|
||||
#ifdef TAL_USE_TALLOC
|
||||
static inline bool no_children(const void *ctx)
|
||||
{
|
||||
return talloc_total_blocks(ctx) == 1;
|
||||
}
|
||||
|
||||
static inline bool single_child(const void *ctx, const void *child)
|
||||
{
|
||||
return talloc_total_blocks(ctx) == 2 && tal_parent(child) == ctx;
|
||||
}
|
||||
#else
|
||||
static inline bool no_children(const void *ctx)
|
||||
{
|
||||
return !tal_first(ctx);
|
||||
}
|
||||
|
||||
static inline bool single_child(const void *ctx, const void *child)
|
||||
{
|
||||
return tal_first(ctx) == child && !tal_next(ctx, child);
|
||||
}
|
||||
#endif
|
@ -1,90 +0,0 @@
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <ccan/tal/str/str.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
#include "helper.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char *parent, *c;
|
||||
|
||||
plan_tests(32);
|
||||
|
||||
parent = tal(NULL, char);
|
||||
ok1(parent);
|
||||
|
||||
c = tal_strdup(parent, "hello");
|
||||
ok1(strcmp(c, "hello") == 0);
|
||||
ok1(tal_parent(c) == parent);
|
||||
tal_free(c);
|
||||
|
||||
c = tal_strndup(parent, "hello", 3);
|
||||
ok1(strcmp(c, "hel") == 0);
|
||||
ok1(tal_parent(c) == parent);
|
||||
tal_free(c);
|
||||
|
||||
#ifdef TAL_USE_TALLOC
|
||||
c = tal_talloc_typechk_(parent, char *);
|
||||
#else
|
||||
c = tal_typechk_(parent, char *);
|
||||
#endif
|
||||
c = tal_dup_arr(parent, char, "hello", 6, 0);
|
||||
ok1(strcmp(c, "hello") == 0);
|
||||
ok1(strcmp(tal_name(c), "char[]") == 0);
|
||||
ok1(tal_parent(c) == parent);
|
||||
tal_free(c);
|
||||
|
||||
/* Now with an extra byte. */
|
||||
c = tal_dup_arr(parent, char, "hello", 6, 1);
|
||||
ok1(strcmp(c, "hello") == 0);
|
||||
ok1(strcmp(tal_name(c), "char[]") == 0);
|
||||
ok1(tal_parent(c) == parent);
|
||||
strcat(c, "x");
|
||||
tal_free(c);
|
||||
|
||||
c = tal_fmt(parent, "hello %s", "there");
|
||||
ok1(strcmp(c, "hello there") == 0);
|
||||
ok1(tal_parent(c) == parent);
|
||||
tal_free(c);
|
||||
|
||||
c = tal_strcat(parent, "hello ", "there");
|
||||
ok1(strcmp(c, "hello there") == 0);
|
||||
ok1(tal_parent(c) == parent);
|
||||
|
||||
/* Make sure take works correctly. */
|
||||
c = tal_strcat(parent, take(c), " again");
|
||||
ok1(strcmp(c, "hello there again") == 0);
|
||||
ok1(tal_parent(c) == parent);
|
||||
ok1(single_child(parent, c));
|
||||
|
||||
c = tal_strcat(parent, "And ", take(c));
|
||||
ok1(strcmp(c, "And hello there again") == 0);
|
||||
ok1(tal_parent(c) == parent);
|
||||
ok1(single_child(parent, c));
|
||||
|
||||
/* NULL pass through works... */
|
||||
c = tal_strcat(parent, take(NULL), take(c));
|
||||
ok1(!c);
|
||||
ok1(no_children(parent));
|
||||
|
||||
c = tal_strcat(parent, take(tal_strdup(parent, "hi")),
|
||||
take(NULL));
|
||||
ok1(!c);
|
||||
ok1(no_children(parent));
|
||||
|
||||
c = tal_strcat(parent, take(NULL), take(NULL));
|
||||
ok1(!c);
|
||||
ok1(no_children(parent));
|
||||
|
||||
/* Appending formatted strings. */
|
||||
c = tal_strdup(parent, "hi");
|
||||
ok1(tal_append_fmt(&c, "%s %s", "there", "world"));
|
||||
ok1(strcmp(c, "hithere world") == 0);
|
||||
ok1(tal_parent(c) == parent);
|
||||
|
||||
ok1(!tal_append_fmt(&c, take(NULL), "there", "world"));
|
||||
ok1(strcmp(c, "hithere world") == 0);
|
||||
|
||||
tal_free(parent);
|
||||
|
||||
return exit_status();
|
||||
}
|
@ -1,124 +0,0 @@
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <ccan/tal/str/str.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
#include "helper.h"
|
||||
|
||||
static bool find_parent(tal_t *child, tal_t *parent)
|
||||
{
|
||||
tal_t *i;
|
||||
|
||||
for (i = child; i; i = tal_parent(i))
|
||||
if (i == parent)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
void *ctx = tal_strdup(NULL, "toplevel");
|
||||
char *a, *b;
|
||||
/* If it accesses this, it will crash. */
|
||||
char **invalid = (char **)1L;
|
||||
|
||||
plan_tests(41);
|
||||
/* Simple matching. */
|
||||
ok1(tal_strreg(ctx, "hello world!", "hello") == true);
|
||||
ok1(tal_strreg(ctx, "hello world!", "hi") == false);
|
||||
|
||||
/* No parentheses means we don't use any extra args. */
|
||||
ok1(tal_strreg(ctx, "hello world!", "hello", invalid) == true);
|
||||
ok1(tal_strreg(ctx, "hello world!", "hi", invalid) == false);
|
||||
|
||||
ok1(tal_strreg(ctx, "hello world!", "[a-z]+", invalid) == true);
|
||||
ok1(tal_strreg(ctx, "hello world!", "([a-z]+)", &a, invalid) == true);
|
||||
/* Found string */
|
||||
ok1(streq(a, "hello"));
|
||||
/* Allocated off ctx */
|
||||
ok1(find_parent(a, ctx));
|
||||
tal_free(a);
|
||||
|
||||
ok1(tal_strreg(ctx, "hello world!", "([a-z]*) ([a-z]+)",
|
||||
&a, &b, invalid) == true);
|
||||
ok1(streq(a, "hello"));
|
||||
ok1(streq(b, "world"));
|
||||
ok1(find_parent(a, ctx));
|
||||
ok1(find_parent(b, ctx));
|
||||
tal_free(a);
|
||||
tal_free(b);
|
||||
|
||||
/* * after parentheses returns last match. */
|
||||
ok1(tal_strreg(ctx, "hello world!", "([a-z])* ([a-z]+)",
|
||||
&a, &b, invalid) == true);
|
||||
ok1(streq(a, "o"));
|
||||
ok1(streq(b, "world"));
|
||||
tal_free(a);
|
||||
tal_free(b);
|
||||
|
||||
/* Nested parentheses are ordered by open brace. */
|
||||
ok1(tal_strreg(ctx, "hello world!", "(([a-z]*) world)",
|
||||
&a, &b, invalid) == true);
|
||||
ok1(streq(a, "hello world"));
|
||||
ok1(streq(b, "hello"));
|
||||
tal_free(a);
|
||||
tal_free(b);
|
||||
|
||||
/* Nested parentheses are ordered by open brace. */
|
||||
ok1(tal_strreg(ctx, "hello world!", "(([a-z]*) world)",
|
||||
&a, &b, invalid) == true);
|
||||
ok1(streq(a, "hello world"));
|
||||
ok1(streq(b, "hello"));
|
||||
tal_free(a);
|
||||
tal_free(b);
|
||||
|
||||
/* NULL means we're not interested. */
|
||||
ok1(tal_strreg(ctx, "hello world!", "((hello|goodbye) world)",
|
||||
&a, NULL, invalid) == true);
|
||||
ok1(streq(a, "hello world"));
|
||||
tal_free(a);
|
||||
|
||||
/* No leaks! */
|
||||
ok1(no_children(ctx));
|
||||
|
||||
/* NULL arg with take means always fail. */
|
||||
ok1(tal_strreg(ctx, take(NULL), "((hello|goodbye) world)",
|
||||
&b, NULL, invalid) == false);
|
||||
|
||||
/* Take string. */
|
||||
a = tal_strdup(ctx, "hello world!");
|
||||
ok1(tal_strreg(ctx, take(a), "([a-z]+)", &b, invalid) == true);
|
||||
ok1(streq(b, "hello"));
|
||||
ok1(tal_parent(b) == ctx);
|
||||
tal_free(b);
|
||||
ok1(no_children(ctx));
|
||||
|
||||
/* Take regex. */
|
||||
a = tal_strdup(ctx, "([a-z]+)");
|
||||
ok1(tal_strreg(ctx, "hello world!", take(a), &b, invalid) == true);
|
||||
ok1(streq(b, "hello"));
|
||||
ok1(tal_parent(b) == ctx);
|
||||
tal_free(b);
|
||||
ok1(no_children(ctx));
|
||||
|
||||
/* Take both. */
|
||||
a = tal_strdup(ctx, "([a-z]+)");
|
||||
ok1(tal_strreg(ctx, take(tal_strdup(ctx, "hello world!")),
|
||||
take(a), &b, invalid) == true);
|
||||
ok1(streq(b, "hello"));
|
||||
ok1(tal_parent(b) == ctx);
|
||||
tal_free(b);
|
||||
ok1(no_children(ctx));
|
||||
|
||||
/* ... even if we fail to match. */
|
||||
a = tal_strdup(ctx, "([a-z]+)");
|
||||
ok1(tal_strreg(ctx, take(tal_strdup(ctx, "HELLO WORLD!")),
|
||||
take(a), &b, invalid) == false);
|
||||
ok1(no_children(ctx));
|
||||
tal_free(ctx);
|
||||
|
||||
/* Don't get fooled by \(! */
|
||||
ok1(tal_strreg(ctx, "(hello) (world)!", "\\([a-z]*\\) \\([a-z]+\\)",
|
||||
invalid) == true);
|
||||
|
||||
return exit_status();
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <ccan/tal/str/str.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
#include "helper.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char *parent, *c;
|
||||
|
||||
plan_tests(14);
|
||||
|
||||
parent = tal(NULL, char);
|
||||
ok1(parent);
|
||||
|
||||
c = tal_strdup(parent, "hello");
|
||||
|
||||
c = tal_strdup(parent, take(c));
|
||||
ok1(strcmp(c, "hello") == 0);
|
||||
ok1(tal_parent(c) == parent);
|
||||
|
||||
c = tal_strndup(parent, take(c), 5);
|
||||
ok1(strcmp(c, "hello") == 0);
|
||||
ok1(tal_parent(c) == parent);
|
||||
|
||||
c = tal_strndup(parent, take(c), 3);
|
||||
ok1(strcmp(c, "hel") == 0);
|
||||
ok1(tal_parent(c) == parent);
|
||||
tal_free(c);
|
||||
|
||||
c = tal_strdup(parent, "hello %s");
|
||||
c = tal_fmt(parent, take(c), "there");
|
||||
ok1(strcmp(c, "hello there") == 0);
|
||||
ok1(tal_parent(c) == parent);
|
||||
/* No leftover allocations. */
|
||||
tal_free(c);
|
||||
ok1(no_children(parent));
|
||||
|
||||
tal_free(parent);
|
||||
ok1(!taken_any());
|
||||
|
||||
/* NULL pass-through. */
|
||||
c = NULL;
|
||||
ok1(tal_strdup(NULL, take(c)) == NULL);
|
||||
ok1(tal_strndup(NULL, take(c), 5) == NULL);
|
||||
ok1(tal_fmt(NULL, take(c), 0) == NULL);
|
||||
|
||||
return exit_status();
|
||||
}
|
@ -1,158 +0,0 @@
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ccan/tal/str/str.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
#include "helper.h"
|
||||
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
|
||||
|
||||
static const char *substrings[]
|
||||
= { "far", "bar", "baz", "b", "ba", "z", "ar", NULL };
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char **split, *str;
|
||||
void *ctx;
|
||||
|
||||
plan_tests(69);
|
||||
split = tal_strsplit(NULL, "hello world", " ", STR_EMPTY_OK);
|
||||
ok1(!strcmp(split[0], "hello"));
|
||||
ok1(!strcmp(split[1], ""));
|
||||
ok1(!strcmp(split[2], "world"));
|
||||
ok1(split[3] == NULL);
|
||||
ok1(tal_count(split) == 4);
|
||||
tal_free(split);
|
||||
|
||||
split = tal_strsplit(NULL, "hello world", " ", STR_NO_EMPTY);
|
||||
ok1(!strcmp(split[0], "hello"));
|
||||
ok1(!strcmp(split[1], "world"));
|
||||
ok1(split[2] == NULL);
|
||||
ok1(tal_count(split) == 3);
|
||||
tal_free(split);
|
||||
|
||||
split = tal_strsplit(NULL, " hello world", " ", STR_NO_EMPTY);
|
||||
ok1(!strcmp(split[0], "hello"));
|
||||
ok1(!strcmp(split[1], "world"));
|
||||
ok1(split[2] == NULL);
|
||||
ok1(tal_count(split) == 3);
|
||||
tal_free(split);
|
||||
|
||||
split = tal_strsplit(NULL, "hello world", "o ", STR_EMPTY_OK);
|
||||
ok1(!strcmp(split[0], "hell"));
|
||||
ok1(!strcmp(split[1], ""));
|
||||
ok1(!strcmp(split[2], ""));
|
||||
ok1(!strcmp(split[3], "w"));
|
||||
ok1(!strcmp(split[4], "rld"));
|
||||
ok1(split[5] == NULL);
|
||||
ok1(tal_count(split) == 6);
|
||||
|
||||
ctx = split;
|
||||
split = tal_strsplit(ctx, "hello world", "o ", STR_EMPTY_OK);
|
||||
ok1(tal_parent(split) == ctx);
|
||||
tal_free(ctx);
|
||||
|
||||
str = tal_strjoin(NULL, (char **)substrings, ", ", STR_TRAIL);
|
||||
ok1(!strcmp(str, "far, bar, baz, b, ba, z, ar, "));
|
||||
ctx = str;
|
||||
str = tal_strjoin(ctx, (char **)substrings, "", STR_TRAIL);
|
||||
ok1(!strcmp(str, "farbarbazbbazar"));
|
||||
ok1(tal_parent(str) == ctx);
|
||||
str = tal_strjoin(ctx, (char **)substrings, ", ", STR_NO_TRAIL);
|
||||
ok1(tal_parent(str) == ctx);
|
||||
ok1(!strcmp(str, "far, bar, baz, b, ba, z, ar"));
|
||||
str = tal_strjoin(ctx, (char **)substrings, "", STR_NO_TRAIL);
|
||||
ok1(!strcmp(str, "farbarbazbbazar"));
|
||||
ok1(tal_parent(str) == ctx);
|
||||
tal_free(ctx);
|
||||
|
||||
ctx = tal_strdup(NULL, "context");
|
||||
/* Pass through NULLs from take. */
|
||||
ok1(tal_strsplit(NULL, take(NULL), " ", STR_EMPTY_OK) == NULL);
|
||||
ok1(tal_strsplit(NULL, "foo", take(NULL), STR_EMPTY_OK) == NULL);
|
||||
|
||||
/* tal_strsplit take string. It reallocs it to same size, but
|
||||
* that sometimes causes a move, so we can't directly check
|
||||
* that split[0] == str. */
|
||||
str = tal_strdup(ctx, "hello world");
|
||||
ok1(tal_check(ctx, NULL));
|
||||
ok1(tal_check(str, NULL));
|
||||
split = tal_strsplit(ctx, take(str), " ", STR_EMPTY_OK);
|
||||
ok1(tal_parent(split) == ctx);
|
||||
ok1(!strcmp(split[0], "hello"));
|
||||
ok1(!strcmp(split[1], "world"));
|
||||
ok1(split[2] == NULL);
|
||||
ok1(tal_check(split, NULL));
|
||||
ok1(tal_check(ctx, NULL));
|
||||
tal_free(split);
|
||||
/* Previous free should get rid of str */
|
||||
ok1(no_children(ctx));
|
||||
|
||||
/* tal_strsplit take delims */
|
||||
str = tal_strdup(ctx, " ");
|
||||
split = tal_strsplit(ctx, "hello world", take(str), STR_EMPTY_OK);
|
||||
ok1(tal_parent(split) == ctx);
|
||||
ok1(!strcmp(split[0], "hello"));
|
||||
ok1(!strcmp(split[1], "world"));
|
||||
ok1(split[2] == NULL);
|
||||
ok1(tal_check(split, NULL));
|
||||
ok1(tal_check(ctx, NULL));
|
||||
tal_free(split);
|
||||
/* str is gone... */
|
||||
ok1(no_children(ctx));
|
||||
|
||||
/* tal_strsplit takes both. */
|
||||
split = tal_strsplit(ctx, take(tal_strdup(NULL, "hello world")),
|
||||
take(tal_strdup(NULL, " ")), STR_EMPTY_OK);
|
||||
ok1(tal_parent(split) == ctx);
|
||||
ok1(!strcmp(split[0], "hello"));
|
||||
ok1(!strcmp(split[1], "world"));
|
||||
ok1(split[2] == NULL);
|
||||
ok1(tal_check(split, NULL));
|
||||
ok1(tal_check(ctx, NULL));
|
||||
tal_free(split);
|
||||
/* temp allocs are gone... */
|
||||
ok1(no_children(ctx));
|
||||
|
||||
/* tal_strjoin passthrough taken NULLs OK. */
|
||||
ok1(tal_strjoin(ctx, take(NULL), "", STR_TRAIL) == NULL);
|
||||
ok1(tal_strjoin(ctx, take(NULL), "", STR_NO_TRAIL) == NULL);
|
||||
ok1(tal_strjoin(ctx, split, take(NULL), STR_TRAIL) == NULL);
|
||||
ok1(tal_strjoin(ctx, split, take(NULL), STR_NO_TRAIL) == NULL);
|
||||
|
||||
/* tal_strjoin take strings[] */
|
||||
split = tal_strsplit(ctx, "hello world", " ", STR_EMPTY_OK);
|
||||
str = tal_strjoin(ctx, take(split), " there ", STR_NO_TRAIL);
|
||||
ok1(!strcmp(str, "hello there world"));
|
||||
ok1(tal_parent(str) == ctx);
|
||||
/* split is gone... */
|
||||
ok1(single_child(ctx, str));
|
||||
tal_free(str);
|
||||
ok1(no_children(ctx));
|
||||
|
||||
/* tal_strjoin take delim */
|
||||
split = tal_strsplit(ctx, "hello world", " ", STR_EMPTY_OK);
|
||||
str = tal_strjoin(ctx, split, take(tal_strdup(ctx, " there ")),
|
||||
STR_NO_TRAIL);
|
||||
ok1(!strcmp(str, "hello there world"));
|
||||
ok1(tal_parent(str) == ctx);
|
||||
tal_free(split);
|
||||
/* tmp alloc is gone, str is only remainder. */
|
||||
ok1(single_child(ctx, str));
|
||||
tal_free(str);
|
||||
ok1(no_children(ctx));
|
||||
|
||||
/* tal_strjoin take both. */
|
||||
str = tal_strjoin(ctx, take(tal_strsplit(ctx, "hello world", " ",
|
||||
STR_EMPTY_OK)),
|
||||
take(tal_strdup(ctx, " there ")), STR_NO_TRAIL);
|
||||
ok1(!strcmp(str, "hello there world"));
|
||||
ok1(tal_parent(str) == ctx);
|
||||
/* tmp allocs are gone, str is only remainder. */
|
||||
ok1(single_child(ctx, str));
|
||||
tal_free(str);
|
||||
ok1(no_children(ctx));
|
||||
tal_free(ctx);
|
||||
|
||||
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