mirror of https://github.com/lukechilds/damus.git
Browse Source
We'll need this for our lightning invoice view Signed-off-by: William Casarin <jb55@jb55.com>profile-edit
William Casarin
2 years ago
44 changed files with 8280 additions and 0 deletions
@ -0,0 +1,20 @@ |
|||
/* CC0 (Public domain) - see LICENSE file for details */ |
|||
#ifndef CCAN_ALIGNOF_H |
|||
#define CCAN_ALIGNOF_H |
|||
#include "config.h" |
|||
|
|||
/**
|
|||
* ALIGNOF - get the alignment of a type |
|||
* @t: the type to test |
|||
* |
|||
* This returns a safe alignment for the given type. |
|||
*/ |
|||
#if HAVE_ALIGNOF |
|||
/* A GCC extension. */ |
|||
#define ALIGNOF(t) __alignof__(t) |
|||
#else |
|||
/* Alignment by measuring structure padding. */ |
|||
#define ALIGNOF(t) ((char *)(&((struct { char c; t _h; } *)0)->_h) - (char *)0) |
|||
#endif |
|||
|
|||
#endif /* CCAN_ALIGNOF_H */ |
@ -0,0 +1,566 @@ |
|||
#include "config.h" |
|||
#include <assert.h> |
|||
#include "mem.h" |
|||
#include "talstr.h" |
|||
#include "amount.h" |
|||
#include "overflows.h" |
|||
#include <inttypes.h> |
|||
|
|||
bool amount_sat_to_msat(struct amount_msat *msat, |
|||
struct amount_sat sat) |
|||
{ |
|||
if (mul_overflows_u64(sat.satoshis, MSAT_PER_SAT)) |
|||
return false; |
|||
msat->millisatoshis = sat.satoshis * MSAT_PER_SAT; |
|||
return true; |
|||
} |
|||
|
|||
bool amount_msat_to_sat(struct amount_sat *sat, |
|||
struct amount_msat msat) |
|||
{ |
|||
if (msat.millisatoshis % MSAT_PER_SAT) |
|||
return false; |
|||
sat->satoshis = msat.millisatoshis / MSAT_PER_SAT; |
|||
return true; |
|||
} |
|||
|
|||
|
|||
/* You can always truncate millisatoshis->satoshis. */ |
|||
struct amount_sat amount_msat_to_sat_round_down(struct amount_msat msat) |
|||
{ |
|||
struct amount_sat sat; |
|||
|
|||
sat.satoshis = msat.millisatoshis / MSAT_PER_SAT; |
|||
return sat; |
|||
} |
|||
|
|||
/* Different formatting by amounts: btc, sat and msat */ |
|||
const char *fmt_amount_msat_btc(const tal_t *ctx, |
|||
struct amount_msat msat, |
|||
bool append_unit) |
|||
{ |
|||
if (msat.millisatoshis == 0) |
|||
return tal_fmt(ctx, append_unit ? "0btc" : "0"); |
|||
|
|||
return tal_fmt(ctx, "%"PRIu64".%011"PRIu64"%s", |
|||
msat.millisatoshis / MSAT_PER_BTC, |
|||
msat.millisatoshis % MSAT_PER_BTC, |
|||
append_unit ? "btc" : ""); |
|||
} |
|||
|
|||
const char *fmt_amount_msat(const tal_t *ctx, struct amount_msat msat) |
|||
{ |
|||
return tal_fmt(ctx, "%"PRIu64"msat", msat.millisatoshis); |
|||
} |
|||
|
|||
const char *fmt_amount_sat_btc(const tal_t *ctx, |
|||
struct amount_sat sat, |
|||
bool append_unit) |
|||
{ |
|||
if (sat.satoshis == 0) |
|||
return tal_fmt(ctx, append_unit ? "0btc" : "0"); |
|||
|
|||
return tal_fmt(ctx, "%"PRIu64".%08"PRIu64"%s", |
|||
sat.satoshis / SAT_PER_BTC, |
|||
sat.satoshis % SAT_PER_BTC, |
|||
append_unit ? "btc" : ""); |
|||
} |
|||
|
|||
const char *fmt_amount_sat(const tal_t *ctx, struct amount_sat sat) |
|||
{ |
|||
return tal_fmt(ctx, "%"PRIu64"sat", sat.satoshis); |
|||
} |
|||
|
|||
static bool breakup(const char *str, size_t slen, |
|||
/* Length of first numeric part. */ |
|||
size_t *whole_number_len, |
|||
/* Pointer to post-decimal part, or NULL */ |
|||
const char **post_decimal_ptr, |
|||
size_t *post_decimal_len, |
|||
/* Pointer to suffix, or NULL */ |
|||
const char **suffix_ptr, |
|||
size_t *suffix_len) |
|||
{ |
|||
size_t i; |
|||
|
|||
*whole_number_len = 0; |
|||
*post_decimal_len = 0; |
|||
*post_decimal_ptr = NULL; |
|||
*suffix_ptr = NULL; |
|||
*suffix_len = 0; |
|||
|
|||
for (i = 0;; i++) { |
|||
/* The string may be null-terminated. */ |
|||
if (i >= slen || str[i] == '\0') |
|||
return i != 0; |
|||
if (cisdigit(str[i])) |
|||
(*whole_number_len)++; |
|||
else |
|||
break; |
|||
} |
|||
|
|||
if (str[i] == '.') { |
|||
i++; |
|||
*post_decimal_ptr = str + i; |
|||
for (;; i++) { |
|||
/* True if > 0 decimals. */ |
|||
if (i >= slen || str[i] == '\0') |
|||
return str + i != *post_decimal_ptr; |
|||
if (cisdigit(str[i])) |
|||
(*post_decimal_len)++; |
|||
else |
|||
break; |
|||
} |
|||
} |
|||
|
|||
*suffix_ptr = str + i; |
|||
*suffix_len = slen - i; |
|||
return true; |
|||
} |
|||
|
|||
static bool from_number(u64 *res, const char *s, size_t len, int tens_factor) |
|||
{ |
|||
if (len == 0) |
|||
return false; |
|||
|
|||
*res = 0; |
|||
for (size_t i = 0; i < len; i++) { |
|||
if (mul_overflows_u64(*res, 10)) |
|||
return false; |
|||
*res *= 10; |
|||
assert(cisdigit(s[i])); |
|||
if (add_overflows_u64(*res, s[i] - '0')) |
|||
return false; |
|||
*res += s[i] - '0'; |
|||
} |
|||
while (tens_factor > 0) { |
|||
if (mul_overflows_u64(*res, 10)) |
|||
return false; |
|||
*res *= 10; |
|||
tens_factor--; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
static bool from_numbers(u64 *res, |
|||
const char *s1, size_t len1, int tens_factor, |
|||
const char *s2, size_t len2) |
|||
{ |
|||
u64 p1, p2; |
|||
if (len2 > tens_factor) |
|||
return false; |
|||
|
|||
if (!from_number(&p1, s1, len1, tens_factor) |
|||
|| !from_number(&p2, s2, len2, tens_factor - len2)) |
|||
return false; |
|||
|
|||
if (add_overflows_u64(p1, p2)) |
|||
return false; |
|||
|
|||
*res = p1 + p2; |
|||
return true; |
|||
} |
|||
|
|||
/* Valid strings:
|
|||
* [0-9]+ => millisatoshi. |
|||
* [0-9]+msat => millisatoshi. |
|||
* [0-9]+sat => *1000 -> millisatoshi. |
|||
* [0-9]+.[0-9]{1,11}btc => millisatoshi. |
|||
*/ |
|||
bool parse_amount_msat(struct amount_msat *msat, const char *s, size_t slen) |
|||
{ |
|||
size_t whole_number_len, post_decimal_len, suffix_len; |
|||
const char *post_decimal_ptr, *suffix_ptr; |
|||
|
|||
if (!breakup(s, slen, &whole_number_len, |
|||
&post_decimal_ptr, &post_decimal_len, |
|||
&suffix_ptr, &suffix_len)) |
|||
return false; |
|||
|
|||
if (!post_decimal_ptr && !suffix_ptr) |
|||
return from_number(&msat->millisatoshis, s, whole_number_len, 0); |
|||
if (!post_decimal_ptr && memstarts_str(suffix_ptr, suffix_len, "msat")) |
|||
return from_number(&msat->millisatoshis, s, whole_number_len, 0); |
|||
if (!post_decimal_ptr && memstarts_str(suffix_ptr, suffix_len, "sat")) |
|||
return from_number(&msat->millisatoshis, s, whole_number_len, 3); |
|||
if (memstarts_str(suffix_ptr, suffix_len, "btc")) { |
|||
if (post_decimal_len > 0) |
|||
return from_numbers(&msat->millisatoshis, |
|||
s, whole_number_len, 11, |
|||
post_decimal_ptr, post_decimal_len); |
|||
return from_number(&msat->millisatoshis, s, whole_number_len, 11); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/* Valid strings:
|
|||
* [0-9]+ => satoshi. |
|||
* [0-9]+sat => satoshi. |
|||
* [0-9]+000msat => satoshi. |
|||
* 0msat => 0 satoshi |
|||
* [0-9]+.[0-9]{1,8}btc => satoshi. |
|||
*/ |
|||
bool parse_amount_sat(struct amount_sat *sat, const char *s, size_t slen) |
|||
{ |
|||
size_t whole_number_len, post_decimal_len, suffix_len; |
|||
const char *post_decimal_ptr, *suffix_ptr; |
|||
|
|||
if (!breakup(s, slen, &whole_number_len, |
|||
&post_decimal_ptr, &post_decimal_len, |
|||
&suffix_ptr, &suffix_len)) |
|||
return false; |
|||
|
|||
if (!post_decimal_ptr && !suffix_ptr) |
|||
return from_number(&sat->satoshis, s, whole_number_len, 0); |
|||
if (!post_decimal_ptr && memstarts_str(suffix_ptr, suffix_len, "sat")) |
|||
return from_number(&sat->satoshis, s, whole_number_len, 0); |
|||
if (!post_decimal_ptr && memstarts_str(suffix_ptr, suffix_len, "msat")) { |
|||
if (!memends(s, whole_number_len, "000", strlen("000"))) { |
|||
if (memstarts_str(s, whole_number_len, "0")) |
|||
return from_number(&sat->satoshis, s, |
|||
whole_number_len, 0); |
|||
return false; |
|||
} |
|||
return from_number(&sat->satoshis, s, whole_number_len - 3, 0); |
|||
} |
|||
if (memstarts_str(suffix_ptr, suffix_len, "btc")) { |
|||
if (post_decimal_len > 0) |
|||
return from_numbers(&sat->satoshis, |
|||
s, whole_number_len, 8, |
|||
post_decimal_ptr, post_decimal_len); |
|||
return from_number(&sat->satoshis, s, whole_number_len, 8); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
WARN_UNUSED_RESULT bool amount_msat_add(struct amount_msat *val, |
|||
struct amount_msat a, |
|||
struct amount_msat b) |
|||
{ |
|||
if (add_overflows_u64(a.millisatoshis, b.millisatoshis)) |
|||
return false; |
|||
|
|||
val->millisatoshis = a.millisatoshis + b.millisatoshis; |
|||
return true; |
|||
} |
|||
|
|||
WARN_UNUSED_RESULT bool amount_msat_sub(struct amount_msat *val, |
|||
struct amount_msat a, |
|||
struct amount_msat b) |
|||
{ |
|||
if (a.millisatoshis < b.millisatoshis) |
|||
return false; |
|||
|
|||
val->millisatoshis = a.millisatoshis - b.millisatoshis; |
|||
return true; |
|||
} |
|||
|
|||
WARN_UNUSED_RESULT bool amount_sat_add(struct amount_sat *val, |
|||
struct amount_sat a, |
|||
struct amount_sat b) |
|||
{ |
|||
if (add_overflows_u64(a.satoshis, b.satoshis)) |
|||
return false; |
|||
|
|||
val->satoshis = a.satoshis + b.satoshis; |
|||
return true; |
|||
} |
|||
|
|||
WARN_UNUSED_RESULT bool amount_sat_sub(struct amount_sat *val, |
|||
struct amount_sat a, |
|||
struct amount_sat b) |
|||
{ |
|||
if (a.satoshis < b.satoshis) |
|||
return false; |
|||
|
|||
val->satoshis = a.satoshis - b.satoshis; |
|||
return true; |
|||
} |
|||
|
|||
WARN_UNUSED_RESULT bool amount_msat_sub_sat(struct amount_msat *val, |
|||
struct amount_msat a, |
|||
struct amount_sat b) |
|||
{ |
|||
struct amount_msat msatb; |
|||
|
|||
if (!amount_sat_to_msat(&msatb, b)) |
|||
return false; |
|||
|
|||
return amount_msat_sub(val, a, msatb); |
|||
} |
|||
|
|||
WARN_UNUSED_RESULT bool amount_sat_sub_msat(struct amount_msat *val, |
|||
struct amount_sat a, |
|||
struct amount_msat b) |
|||
{ |
|||
struct amount_msat msata; |
|||
|
|||
if (!amount_sat_to_msat(&msata, a)) |
|||
return false; |
|||
|
|||
return amount_msat_sub(val, msata, b); |
|||
} |
|||
|
|||
WARN_UNUSED_RESULT bool amount_msat_add_sat(struct amount_msat *val, |
|||
struct amount_msat a, |
|||
struct amount_sat b) |
|||
{ |
|||
struct amount_msat msatb; |
|||
|
|||
if (!amount_sat_to_msat(&msatb, b)) |
|||
return false; |
|||
|
|||
return amount_msat_add(val, a, msatb); |
|||
} |
|||
|
|||
WARN_UNUSED_RESULT bool amount_msat_scale(struct amount_msat *val, |
|||
struct amount_msat msat, |
|||
double scale) |
|||
{ |
|||
double scaled = msat.millisatoshis * scale; |
|||
|
|||
/* If mantissa is < 64 bits, a naive "if (scaled >
|
|||
* UINT64_MAX)" doesn't work. Stick to powers of 2. */ |
|||
if (scaled >= (double)((u64)1 << 63) * 2) |
|||
return false; |
|||
val->millisatoshis = scaled; |
|||
return true; |
|||
} |
|||
|
|||
WARN_UNUSED_RESULT bool amount_sat_scale(struct amount_sat *val, |
|||
struct amount_sat sat, |
|||
double scale) |
|||
{ |
|||
double scaled = sat.satoshis * scale; |
|||
|
|||
/* If mantissa is < 64 bits, a naive "if (scaled >
|
|||
* UINT64_MAX)" doesn't work. Stick to powers of 2. */ |
|||
if (scaled >= (double)((u64)1 << 63) * 2) |
|||
return false; |
|||
val->satoshis = scaled; |
|||
return true; |
|||
} |
|||
|
|||
bool amount_sat_eq(struct amount_sat a, struct amount_sat b) |
|||
{ |
|||
return a.satoshis == b.satoshis; |
|||
} |
|||
|
|||
bool amount_sat_zero(struct amount_sat a) |
|||
{ |
|||
return a.satoshis == 0; |
|||
} |
|||
|
|||
bool amount_msat_zero(struct amount_msat a) |
|||
{ |
|||
return a.millisatoshis == 0; |
|||
} |
|||
|
|||
bool amount_msat_eq(struct amount_msat a, struct amount_msat b) |
|||
{ |
|||
return a.millisatoshis == b.millisatoshis; |
|||
} |
|||
|
|||
bool amount_sat_greater(struct amount_sat a, struct amount_sat b) |
|||
{ |
|||
return a.satoshis > b.satoshis; |
|||
} |
|||
|
|||
bool amount_msat_greater(struct amount_msat a, struct amount_msat b) |
|||
{ |
|||
return a.millisatoshis > b.millisatoshis; |
|||
} |
|||
|
|||
bool amount_sat_greater_eq(struct amount_sat a, struct amount_sat b) |
|||
{ |
|||
return a.satoshis >= b.satoshis; |
|||
} |
|||
|
|||
bool amount_msat_greater_eq(struct amount_msat a, struct amount_msat b) |
|||
{ |
|||
return a.millisatoshis >= b.millisatoshis; |
|||
} |
|||
|
|||
bool amount_sat_less(struct amount_sat a, struct amount_sat b) |
|||
{ |
|||
return a.satoshis < b.satoshis; |
|||
} |
|||
|
|||
bool amount_msat_less(struct amount_msat a, struct amount_msat b) |
|||
{ |
|||
return a.millisatoshis < b.millisatoshis; |
|||
} |
|||
|
|||
bool amount_sat_less_eq(struct amount_sat a, struct amount_sat b) |
|||
{ |
|||
return a.satoshis <= b.satoshis; |
|||
} |
|||
|
|||
bool amount_msat_less_eq(struct amount_msat a, struct amount_msat b) |
|||
{ |
|||
return a.millisatoshis <= b.millisatoshis; |
|||
} |
|||
|
|||
bool amount_msat_greater_sat(struct amount_msat msat, struct amount_sat sat) |
|||
{ |
|||
struct amount_msat msat_from_sat; |
|||
|
|||
if (!amount_sat_to_msat(&msat_from_sat, sat)) |
|||
return false; |
|||
return msat.millisatoshis > msat_from_sat.millisatoshis; |
|||
} |
|||
|
|||
bool amount_msat_greater_eq_sat(struct amount_msat msat, struct amount_sat sat) |
|||
{ |
|||
struct amount_msat msat_from_sat; |
|||
|
|||
if (!amount_sat_to_msat(&msat_from_sat, sat)) |
|||
return false; |
|||
return msat.millisatoshis >= msat_from_sat.millisatoshis; |
|||
} |
|||
|
|||
bool amount_msat_less_sat(struct amount_msat msat, struct amount_sat sat) |
|||
{ |
|||
struct amount_msat msat_from_sat; |
|||
|
|||
if (!amount_sat_to_msat(&msat_from_sat, sat)) |
|||
return false; |
|||
return msat.millisatoshis < msat_from_sat.millisatoshis; |
|||
} |
|||
|
|||
bool amount_msat_less_eq_sat(struct amount_msat msat, struct amount_sat sat) |
|||
{ |
|||
struct amount_msat msat_from_sat; |
|||
|
|||
if (!amount_sat_to_msat(&msat_from_sat, sat)) |
|||
return false; |
|||
return msat.millisatoshis <= msat_from_sat.millisatoshis; |
|||
} |
|||
|
|||
bool amount_msat_eq_sat(struct amount_msat msat, struct amount_sat sat) |
|||
{ |
|||
struct amount_msat msat_from_sat; |
|||
|
|||
if (!amount_sat_to_msat(&msat_from_sat, sat)) |
|||
return false; |
|||
|
|||
return msat.millisatoshis == msat_from_sat.millisatoshis; |
|||
} |
|||
|
|||
bool amount_msat_to_u32(struct amount_msat msat, u32 *millisatoshis) |
|||
{ |
|||
if (amount_msat_greater_eq(msat, AMOUNT_MSAT(0x100000000))) |
|||
return false; |
|||
*millisatoshis = msat.millisatoshis; |
|||
return true; |
|||
} |
|||
|
|||
struct amount_msat amount_msat(u64 millisatoshis) |
|||
{ |
|||
struct amount_msat msat; |
|||
|
|||
msat.millisatoshis = millisatoshis; |
|||
return msat; |
|||
} |
|||
|
|||
struct amount_sat amount_sat(u64 satoshis) |
|||
{ |
|||
struct amount_sat sat; |
|||
|
|||
sat.satoshis = satoshis; |
|||
return sat; |
|||
} |
|||
|
|||
double amount_msat_ratio(struct amount_msat a, struct amount_msat b) |
|||
{ |
|||
return (double)a.millisatoshis / b.millisatoshis; |
|||
} |
|||
|
|||
struct amount_msat amount_msat_div(struct amount_msat msat, u64 div) |
|||
{ |
|||
msat.millisatoshis /= div; |
|||
return msat; |
|||
} |
|||
|
|||
struct amount_sat amount_sat_div(struct amount_sat sat, u64 div) |
|||
{ |
|||
sat.satoshis /= div; |
|||
return sat; |
|||
} |
|||
|
|||
bool amount_msat_fee(struct amount_msat *fee, |
|||
struct amount_msat amt, |
|||
u32 fee_base_msat, |
|||
u32 fee_proportional_millionths) |
|||
{ |
|||
struct amount_msat fee_base, fee_prop; |
|||
|
|||
/* BOLT #7:
|
|||
* |
|||
* - SHOULD accept HTLCs that pay a fee equal to or greater than: |
|||
* - fee_base_msat + ( amount_to_forward * fee_proportional_millionths / 1000000 ) |
|||
*/ |
|||
fee_base.millisatoshis = fee_base_msat; |
|||
|
|||
if (mul_overflows_u64(amt.millisatoshis, fee_proportional_millionths)) |
|||
return false; |
|||
fee_prop.millisatoshis = amt.millisatoshis * fee_proportional_millionths |
|||
/ 1000000; |
|||
|
|||
return amount_msat_add(fee, fee_base, fee_prop); |
|||
} |
|||
|
|||
bool amount_msat_add_fee(struct amount_msat *amt, |
|||
u32 fee_base_msat, |
|||
u32 fee_proportional_millionths) |
|||
{ |
|||
struct amount_msat fee; |
|||
|
|||
if (!amount_msat_fee(&fee, *amt, |
|||
fee_base_msat, fee_proportional_millionths)) |
|||
return false; |
|||
return amount_msat_add(amt, *amt, fee); |
|||
} |
|||
|
|||
struct amount_sat amount_tx_fee(u32 fee_per_kw, size_t weight) |
|||
{ |
|||
struct amount_sat fee; |
|||
|
|||
/* If this overflows, weight must be > 2^32, which is not a real tx */ |
|||
assert(!mul_overflows_u64(fee_per_kw, weight)); |
|||
fee.satoshis = (u64)fee_per_kw * weight / 1000; |
|||
|
|||
return fee; |
|||
} |
|||
|
|||
/*
|
|||
struct amount_msat fromwire_amount_msat(const u8 **cursor, size_t *max) |
|||
{ |
|||
struct amount_msat msat; |
|||
|
|||
msat.millisatoshis = fromwire_u64(cursor, max); |
|||
return msat; |
|||
} |
|||
|
|||
struct amount_sat fromwire_amount_sat(const u8 **cursor, size_t *max) |
|||
{ |
|||
struct amount_sat sat; |
|||
|
|||
sat.satoshis = fromwire_u64(cursor, max); |
|||
return sat; |
|||
} |
|||
|
|||
void towire_amount_msat(u8 **pptr, const struct amount_msat msat) |
|||
{ |
|||
towire_u64(pptr, msat.millisatoshis); |
|||
} |
|||
|
|||
void towire_amount_sat(u8 **pptr, const struct amount_sat sat) |
|||
{ |
|||
towire_u64(pptr, sat.satoshis); |
|||
} |
|||
|
|||
|
|||
*/ |
@ -0,0 +1,203 @@ |
|||
#ifndef LIGHTNING_COMMON_AMOUNT_H |
|||
#define LIGHTNING_COMMON_AMOUNT_H |
|||
#include "config.h" |
|||
#include "short_types.h" |
|||
#include "tal.h" |
|||
|
|||
#define MSAT_PER_SAT ((u64)1000) |
|||
#define SAT_PER_BTC ((u64)100000000) |
|||
#define MSAT_PER_BTC (MSAT_PER_SAT * SAT_PER_BTC) |
|||
|
|||
/* Use these to wrap amounts, for typesafety. Please use ops where possible,
|
|||
* rather than accessing the members directly. */ |
|||
struct amount_sat { |
|||
/* Amount in satoshis. */ |
|||
u64 satoshis; |
|||
}; |
|||
|
|||
struct amount_msat { |
|||
/* Amount in millisatoshis. */ |
|||
u64 millisatoshis; |
|||
}; |
|||
|
|||
struct amount_asset { |
|||
u64 value; |
|||
u8 asset[33]; /* 1 version byte + 32 byte asset_tag */ |
|||
}; |
|||
|
|||
/* For constants only: others must be built from primitives! */ |
|||
#if HAVE_BUILTIN_CONSTANT_P |
|||
#define AMOUNT_MUST_BE_CONST(c) BUILD_ASSERT_OR_ZERO(IS_COMPILE_CONSTANT(c)) |
|||
#else |
|||
#define AMOUNT_MUST_BE_CONST(c) 0 |
|||
#endif |
|||
|
|||
/* GCC 4.8.5 (Centos 7.6!) thinks struct casts are not constants, so we
|
|||
* need to not use a cast for static initializations. */ |
|||
#define AMOUNT_MSAT_INIT(msat) \ |
|||
{ .millisatoshis = (msat) } |
|||
#define AMOUNT_SAT_INIT(sat) \ |
|||
{ .satoshis = (sat) } |
|||
|
|||
#define AMOUNT_MSAT(constant) \ |
|||
((struct amount_msat){(constant) + AMOUNT_MUST_BE_CONST(constant)}) |
|||
|
|||
#define AMOUNT_SAT(constant) \ |
|||
((struct amount_sat){(constant) + AMOUNT_MUST_BE_CONST(constant)}) |
|||
|
|||
/* We do sometimes need to import from raw types, eg. wally or wire fmt */ |
|||
struct amount_msat amount_msat(u64 millisatoshis); |
|||
struct amount_sat amount_sat(u64 satoshis); |
|||
|
|||
/* You may not always be able to convert satoshis->millisatoshis. */ |
|||
WARN_UNUSED_RESULT bool amount_sat_to_msat(struct amount_msat *msat, |
|||
struct amount_sat sat); |
|||
|
|||
/* You may not always be able to convert millisatoshis->satoshis without rounding. */ |
|||
WARN_UNUSED_RESULT bool amount_msat_to_sat(struct amount_sat *sat, |
|||
struct amount_msat msat); |
|||
|
|||
/* You can always truncate millisatoshis->satoshis. */ |
|||
struct amount_sat amount_msat_to_sat_round_down(struct amount_msat msat); |
|||
|
|||
/* Simple operations: val = a + b, val = a - b. */ |
|||
WARN_UNUSED_RESULT bool amount_msat_add(struct amount_msat *val, |
|||
struct amount_msat a, |
|||
struct amount_msat b); |
|||
WARN_UNUSED_RESULT bool amount_msat_sub(struct amount_msat *val, |
|||
struct amount_msat a, |
|||
struct amount_msat b); |
|||
WARN_UNUSED_RESULT bool amount_sat_add(struct amount_sat *val, |
|||
struct amount_sat a, |
|||
struct amount_sat b); |
|||
WARN_UNUSED_RESULT bool amount_sat_sub(struct amount_sat *val, |
|||
struct amount_sat a, |
|||
struct amount_sat b); |
|||
WARN_UNUSED_RESULT bool amount_msat_sub_sat(struct amount_msat *val, |
|||
struct amount_msat a, |
|||
struct amount_sat b); |
|||
WARN_UNUSED_RESULT bool amount_msat_add_sat(struct amount_msat *val, |
|||
struct amount_msat a, |
|||
struct amount_sat b); |
|||
WARN_UNUSED_RESULT bool amount_sat_sub_msat(struct amount_msat *val, |
|||
struct amount_sat a, |
|||
struct amount_msat b); |
|||
WARN_UNUSED_RESULT bool amount_msat_scale(struct amount_msat *val, |
|||
struct amount_msat msat, |
|||
double scale); |
|||
WARN_UNUSED_RESULT bool amount_sat_scale(struct amount_sat *val, |
|||
struct amount_sat sat, |
|||
double scale); |
|||
|
|||
struct amount_msat amount_msat_div(struct amount_msat msat, u64 div); |
|||
struct amount_sat amount_sat_div(struct amount_sat sat, u64 div); |
|||
|
|||
/* Is a == b? */ |
|||
bool amount_sat_eq(struct amount_sat a, struct amount_sat b); |
|||
bool amount_msat_eq(struct amount_msat a, struct amount_msat b); |
|||
|
|||
/* Is a zero? */ |
|||
bool amount_sat_zero(struct amount_sat a); |
|||
bool amount_msat_zero(struct amount_msat a); |
|||
|
|||
/* Is a > b? */ |
|||
bool amount_sat_greater(struct amount_sat a, struct amount_sat b); |
|||
bool amount_msat_greater(struct amount_msat a, struct amount_msat b); |
|||
|
|||
/* Is a >= b */ |
|||
bool amount_sat_greater_eq(struct amount_sat a, struct amount_sat b); |
|||
bool amount_msat_greater_eq(struct amount_msat a, struct amount_msat b); |
|||
|
|||
/* Is a < b? */ |
|||
bool amount_sat_less(struct amount_sat a, struct amount_sat b); |
|||
bool amount_msat_less(struct amount_msat a, struct amount_msat b); |
|||
|
|||
/* Is a <= b? */ |
|||
bool amount_sat_less_eq(struct amount_sat a, struct amount_sat b); |
|||
bool amount_msat_less_eq(struct amount_msat a, struct amount_msat b); |
|||
|
|||
/* Is msat > sat? */ |
|||
bool amount_msat_greater_sat(struct amount_msat msat, struct amount_sat sat); |
|||
/* Is msat >= sat? */ |
|||
bool amount_msat_greater_eq_sat(struct amount_msat msat, struct amount_sat sat); |
|||
/* Is msat < sat? */ |
|||
bool amount_msat_less_sat(struct amount_msat msat, struct amount_sat sat); |
|||
/* Is msat <= sat? */ |
|||
bool amount_msat_less_eq_sat(struct amount_msat msat, struct amount_sat sat); |
|||
/* Is msat == sat? */ |
|||
bool amount_msat_eq_sat(struct amount_msat msat, struct amount_sat sat); |
|||
|
|||
/* a / b */ |
|||
double amount_msat_ratio(struct amount_msat a, struct amount_msat b); |
|||
|
|||
/* Check whether this asset is actually the main / fee-paying asset of the
|
|||
* current chain. */ |
|||
bool amount_asset_is_main(struct amount_asset *asset); |
|||
|
|||
/* Convert an amount_sat to an amount_asset */ |
|||
struct amount_asset amount_sat_to_asset(struct amount_sat *sat, const u8 *asset); |
|||
|
|||
/* amount_asset_extract_value -Prefix the amount_asset's value
|
|||
* to have the 'explicit' marker. Returns NULL if the |
|||
* asset was originally blinded. |
|||
* FIXME: pass through blinded amounts */ |
|||
u8 *amount_asset_extract_value(const tal_t *ctx, struct amount_asset *asset); |
|||
|
|||
/* Convert from a generic asset to the fee-paying asset if possible. */ |
|||
struct amount_sat amount_asset_to_sat(struct amount_asset *asset); |
|||
|
|||
/* Returns true if msat fits in a u32 value. */ |
|||
WARN_UNUSED_RESULT bool amount_msat_to_u32(struct amount_msat msat, |
|||
u32 *millisatoshis); |
|||
|
|||
/* Common operation: what is the HTLC fee for given feerate? Can overflow! */ |
|||
WARN_UNUSED_RESULT bool amount_msat_fee(struct amount_msat *fee, |
|||
struct amount_msat amt, |
|||
u32 fee_base_msat, |
|||
u32 fee_proportional_millionths); |
|||
|
|||
/* Same, but add into amt. */ |
|||
WARN_UNUSED_RESULT bool amount_msat_add_fee(struct amount_msat *amt, |
|||
u32 fee_base_msat, |
|||
u32 fee_proportional_millionths); |
|||
|
|||
/* What is the fee for this tx weight? */ |
|||
struct amount_sat amount_tx_fee(u32 fee_per_kw, size_t weight); |
|||
|
|||
/* Different formatting by amounts: btc, sat and msat */ |
|||
/* => 1.23456789012btc (11 decimals!) */ |
|||
const char *fmt_amount_msat_btc(const tal_t *ctx, |
|||
struct amount_msat msat, |
|||
bool append_unit); |
|||
/* => 1234msat */ |
|||
const char *fmt_amount_msat(const tal_t *ctx, struct amount_msat msat); |
|||
|
|||
/* => 1.23456789btc (8 decimals!) */ |
|||
const char *fmt_amount_sat_btc(const tal_t *ctx, |
|||
struct amount_sat sat, |
|||
bool append_unit); |
|||
/* => 1234sat */ |
|||
const char *fmt_amount_sat(const tal_t *ctx, struct amount_sat sat); |
|||
|
|||
/* Valid strings:
|
|||
* [0-9]+ => millisatoshi. |
|||
* [0-9]+msat => millisatoshi. |
|||
* [0-9]+sat => *1000 -> millisatopshi. |
|||
* [0-9]+.[0-9]{1,11}btc => millisatoshi. |
|||
*/ |
|||
bool parse_amount_msat(struct amount_msat *msat, const char *s, size_t slen); |
|||
|
|||
/* Valid strings:
|
|||
* [0-9]+ => satoshi. |
|||
* [0-9]+sat => satoshi. |
|||
* [0-9]+000msat => satoshi. |
|||
* [0-9]+.[0-9]{1,8}btc => satoshi. |
|||
*/ |
|||
bool parse_amount_sat(struct amount_sat *sat, const char *s, size_t slen); |
|||
|
|||
/* Marshal/unmarshal functions */ |
|||
struct amount_msat fromwire_amount_msat(const u8 **cursor, size_t *max); |
|||
struct amount_sat fromwire_amount_sat(const u8 **cursor, size_t *max); |
|||
void towire_amount_msat(u8 **pptr, const struct amount_msat msat); |
|||
void towire_amount_sat(u8 **pptr, const struct amount_sat sat); |
|||
#endif /* LIGHTNING_COMMON_AMOUNT_H */ |
@ -0,0 +1,26 @@ |
|||
/* CC0 (Public domain) - see LICENSE file for details */ |
|||
#ifndef CCAN_ARRAY_SIZE_H |
|||
#define CCAN_ARRAY_SIZE_H |
|||
#include "config.h" |
|||
#include "build_assert.h" |
|||
|
|||
/**
|
|||
* ARRAY_SIZE - get the number of elements in a visible array |
|||
* @arr: the array whose size you want. |
|||
* |
|||
* This does not work on pointers, or arrays declared as [], or |
|||
* function parameters. With correct compiler support, such usage |
|||
* will cause a build error (see build_assert). |
|||
*/ |
|||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + _array_size_chk(arr)) |
|||
|
|||
#if HAVE_BUILTIN_TYPES_COMPATIBLE_P && HAVE_TYPEOF |
|||
/* Two gcc extensions.
|
|||
* &a[0] degrades to a pointer: a different type from an array */ |
|||
#define _array_size_chk(arr) \ |
|||
BUILD_ASSERT_OR_ZERO(!__builtin_types_compatible_p(typeof(arr), \ |
|||
typeof(&(arr)[0]))) |
|||
#else |
|||
#define _array_size_chk(arr) 0 |
|||
#endif |
|||
#endif /* CCAN_ALIGNOF_H */ |
@ -0,0 +1,210 @@ |
|||
/* Stolen from https://github.com/sipa/bech32/blob/master/ref/c/segwit_addr.c,
|
|||
* with only the two ' > 90' checks hoisted, and more internals exposed */ |
|||
|
|||
/* Copyright (c) 2017, 2021 Pieter Wuille
|
|||
* |
|||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
* of this software and associated documentation files (the "Software"), to deal |
|||
* in the Software without restriction, including without limitation the rights |
|||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
* copies of the Software, and to permit persons to whom the Software is |
|||
* furnished to do so, subject to the following conditions: |
|||
* |
|||
* The above copyright notice and this permission notice shall be included in |
|||
* all copies or substantial portions of the Software. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|||
* THE SOFTWARE. |
|||
*/ |
|||
#include "config.h" |
|||
#include <assert.h> |
|||
#include "bech32.h" |
|||
#include <string.h> |
|||
|
|||
static uint32_t bech32_polymod_step(uint32_t pre) { |
|||
uint8_t b = pre >> 25; |
|||
return ((pre & 0x1FFFFFF) << 5) ^ |
|||
(-((b >> 0) & 1) & 0x3b6a57b2UL) ^ |
|||
(-((b >> 1) & 1) & 0x26508e6dUL) ^ |
|||
(-((b >> 2) & 1) & 0x1ea119faUL) ^ |
|||
(-((b >> 3) & 1) & 0x3d4233ddUL) ^ |
|||
(-((b >> 4) & 1) & 0x2a1462b3UL); |
|||
} |
|||
|
|||
static uint32_t bech32_final_constant(bech32_encoding enc) { |
|||
if (enc == BECH32_ENCODING_BECH32) return 1; |
|||
if (enc == BECH32_ENCODING_BECH32M) return 0x2bc830a3; |
|||
assert(0); |
|||
} |
|||
|
|||
const char bech32_charset[] = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"; |
|||
|
|||
const int8_t bech32_charset_rev[128] = { |
|||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|||
15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1, |
|||
-1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, |
|||
1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1, |
|||
-1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, |
|||
1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1 |
|||
}; |
|||
|
|||
int bech32_encode(char *output, const char *hrp, const uint8_t *data, size_t data_len, size_t max_input_len, bech32_encoding enc) { |
|||
uint32_t chk = 1; |
|||
size_t i = 0; |
|||
while (hrp[i] != 0) { |
|||
int ch = hrp[i]; |
|||
if (ch < 33 || ch > 126) { |
|||
return 0; |
|||
} |
|||
|
|||
if (ch >= 'A' && ch <= 'Z') return 0; |
|||
chk = bech32_polymod_step(chk) ^ (ch >> 5); |
|||
++i; |
|||
} |
|||
if (i + 7 + data_len > max_input_len) return 0; |
|||
chk = bech32_polymod_step(chk); |
|||
while (*hrp != 0) { |
|||
chk = bech32_polymod_step(chk) ^ (*hrp & 0x1f); |
|||
*(output++) = *(hrp++); |
|||
} |
|||
*(output++) = '1'; |
|||
for (i = 0; i < data_len; ++i) { |
|||
if (*data >> 5) return 0; |
|||
chk = bech32_polymod_step(chk) ^ (*data); |
|||
*(output++) = bech32_charset[*(data++)]; |
|||
} |
|||
for (i = 0; i < 6; ++i) { |
|||
chk = bech32_polymod_step(chk); |
|||
} |
|||
chk ^= bech32_final_constant(enc); |
|||
for (i = 0; i < 6; ++i) { |
|||
*(output++) = bech32_charset[(chk >> ((5 - i) * 5)) & 0x1f]; |
|||
} |
|||
*output = 0; |
|||
return 1; |
|||
} |
|||
|
|||
bech32_encoding bech32_decode(char* hrp, uint8_t *data, size_t *data_len, const char *input, size_t max_input_len) { |
|||
uint32_t chk = 1; |
|||
size_t i; |
|||
size_t input_len = strlen(input); |
|||
size_t hrp_len; |
|||
int have_lower = 0, have_upper = 0; |
|||
if (input_len < 8 || input_len > max_input_len) { |
|||
return BECH32_ENCODING_NONE; |
|||
} |
|||
*data_len = 0; |
|||
while (*data_len < input_len && input[(input_len - 1) - *data_len] != '1') { |
|||
++(*data_len); |
|||
} |
|||
hrp_len = input_len - (1 + *data_len); |
|||
if (1 + *data_len >= input_len || *data_len < 6) { |
|||
return BECH32_ENCODING_NONE; |
|||
} |
|||
*(data_len) -= 6; |
|||
for (i = 0; i < hrp_len; ++i) { |
|||
int ch = input[i]; |
|||
if (ch < 33 || ch > 126) { |
|||
return BECH32_ENCODING_NONE; |
|||
} |
|||
if (ch >= 'a' && ch <= 'z') { |
|||
have_lower = 1; |
|||
} else if (ch >= 'A' && ch <= 'Z') { |
|||
have_upper = 1; |
|||
ch = (ch - 'A') + 'a'; |
|||
} |
|||
hrp[i] = ch; |
|||
chk = bech32_polymod_step(chk) ^ (ch >> 5); |
|||
} |
|||
hrp[i] = 0; |
|||
chk = bech32_polymod_step(chk); |
|||
for (i = 0; i < hrp_len; ++i) { |
|||
chk = bech32_polymod_step(chk) ^ (input[i] & 0x1f); |
|||
} |
|||
++i; |
|||
while (i < input_len) { |
|||
int v = (input[i] & 0x80) ? -1 : bech32_charset_rev[(int)input[i]]; |
|||
if (input[i] >= 'a' && input[i] <= 'z') have_lower = 1; |
|||
if (input[i] >= 'A' && input[i] <= 'Z') have_upper = 1; |
|||
if (v == -1) { |
|||
return BECH32_ENCODING_NONE; |
|||
} |
|||
chk = bech32_polymod_step(chk) ^ v; |
|||
if (i + 6 < input_len) { |
|||
data[i - (1 + hrp_len)] = v; |
|||
} |
|||
++i; |
|||
} |
|||
if (have_lower && have_upper) { |
|||
return BECH32_ENCODING_NONE; |
|||
} |
|||
if (chk == bech32_final_constant(BECH32_ENCODING_BECH32)) { |
|||
return BECH32_ENCODING_BECH32; |
|||
} else if (chk == bech32_final_constant(BECH32_ENCODING_BECH32M)) { |
|||
return BECH32_ENCODING_BECH32M; |
|||
} else { |
|||
return BECH32_ENCODING_NONE; |
|||
} |
|||
} |
|||
|
|||
int bech32_convert_bits(uint8_t* out, size_t* outlen, int outbits, const uint8_t* in, size_t inlen, int inbits, int pad) { |
|||
uint32_t val = 0; |
|||
int bits = 0; |
|||
uint32_t maxv = (((uint32_t)1) << outbits) - 1; |
|||
while (inlen--) { |
|||
val = (val << inbits) | *(in++); |
|||
bits += inbits; |
|||
while (bits >= outbits) { |
|||
bits -= outbits; |
|||
out[(*outlen)++] = (val >> bits) & maxv; |
|||
} |
|||
} |
|||
if (pad) { |
|||
if (bits) { |
|||
out[(*outlen)++] = (val << (outbits - bits)) & maxv; |
|||
} |
|||
} else if (((val << (outbits - bits)) & maxv) || bits >= inbits) { |
|||
return 0; |
|||
} |
|||
return 1; |
|||
} |
|||
|
|||
int segwit_addr_encode(char *output, const char *hrp, int witver, const uint8_t *witprog, size_t witprog_len) { |
|||
uint8_t data[65]; |
|||
size_t datalen = 0; |
|||
bech32_encoding enc = BECH32_ENCODING_BECH32; |
|||
if (witver > 16) return 0; |
|||
if (witver == 0 && witprog_len != 20 && witprog_len != 32) return 0; |
|||
if (witprog_len < 2 || witprog_len > 40) return 0; |
|||
if (witver > 0) enc = BECH32_ENCODING_BECH32M; |
|||
data[0] = witver; |
|||
bech32_convert_bits(data + 1, &datalen, 5, witprog, witprog_len, 8, 1); |
|||
++datalen; |
|||
return bech32_encode(output, hrp, data, datalen, 90, enc); |
|||
} |
|||
|
|||
int segwit_addr_decode(int* witver, uint8_t* witdata, size_t* witdata_len, const char* hrp, const char* addr) { |
|||
uint8_t data[84]; |
|||
char hrp_actual[84]; |
|||
size_t data_len; |
|||
bech32_encoding enc = bech32_decode(hrp_actual, data, &data_len, addr, 90); |
|||
if (enc == BECH32_ENCODING_NONE) return 0; |
|||
if (data_len == 0 || data_len > 65) return 0; |
|||
if (strncmp(hrp, hrp_actual, 84) != 0) return 0; |
|||
if (data[0] > 16) return 0; |
|||
if (data[0] == 0 && enc != BECH32_ENCODING_BECH32) return 0; |
|||
if (data[0] > 0 && enc != BECH32_ENCODING_BECH32M) return 0; |
|||
*witdata_len = 0; |
|||
if (!bech32_convert_bits(witdata, witdata_len, 8, data + 1, data_len - 1, 5, 0)) return 0; |
|||
if (*witdata_len < 2 || *witdata_len > 40) return 0; |
|||
if (data[0] == 0 && *witdata_len != 20 && *witdata_len != 32) return 0; |
|||
*witver = data[0]; |
|||
return 1; |
|||
} |
@ -0,0 +1,134 @@ |
|||
/* Stolen from https://github.com/sipa/bech32/blob/master/ref/c/segwit_addr.h,
|
|||
* with only the two ' > 90' checks hoisted */ |
|||
|
|||
/* Copyright (c) 2017, 2021 Pieter Wuille
|
|||
* |
|||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
* of this software and associated documentation files (the "Software"), to deal |
|||
* in the Software without restriction, including without limitation the rights |
|||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
* copies of the Software, and to permit persons to whom the Software is |
|||
* furnished to do so, subject to the following conditions: |
|||
* |
|||
* The above copyright notice and this permission notice shall be included in |
|||
* all copies or substantial portions of the Software. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|||
* THE SOFTWARE. |
|||
*/ |
|||
|
|||
#ifndef LIGHTNING_COMMON_BECH32_H |
|||
#define LIGHTNING_COMMON_BECH32_H |
|||
#include "config.h" |
|||
|
|||
#include <stdint.h> |
|||
#include <stdlib.h> |
|||
|
|||
/** Encode a SegWit address
|
|||
* |
|||
* Out: output: Pointer to a buffer of size 73 + strlen(hrp) that will be |
|||
* updated to contain the null-terminated address. |
|||
* In: hrp: Pointer to the null-terminated human readable part to use |
|||
* (chain/network specific). |
|||
* ver: Version of the witness program (between 0 and 16 inclusive). |
|||
* prog: Data bytes for the witness program (between 2 and 40 bytes). |
|||
* prog_len: Number of data bytes in prog. |
|||
* Returns 1 if successful. |
|||
*/ |
|||
int segwit_addr_encode( |
|||
char *output, |
|||
const char *hrp, |
|||
int ver, |
|||
const uint8_t *prog, |
|||
size_t prog_len |
|||
); |
|||
|
|||
/** Decode a SegWit address
|
|||
* |
|||
* Out: ver: Pointer to an int that will be updated to contain the witness |
|||
* program version (between 0 and 16 inclusive). |
|||
* prog: Pointer to a buffer of size 40 that will be updated to |
|||
* contain the witness program bytes. |
|||
* prog_len: Pointer to a size_t that will be updated to contain the length |
|||
* of bytes in prog. |
|||
* hrp: Pointer to the null-terminated human readable part that is |
|||
* expected (chain/network specific). |
|||
* addr: Pointer to the null-terminated address. |
|||
* Returns 1 if successful. |
|||
*/ |
|||
int segwit_addr_decode( |
|||
int* ver, |
|||
uint8_t* prog, |
|||
size_t* prog_len, |
|||
const char* hrp, |
|||
const char* addr |
|||
); |
|||
|
|||
/** Supported encodings. */ |
|||
typedef enum { |
|||
BECH32_ENCODING_NONE, |
|||
BECH32_ENCODING_BECH32, |
|||
BECH32_ENCODING_BECH32M |
|||
} bech32_encoding; |
|||
|
|||
/** Encode a Bech32 or Bech32m string
|
|||
* |
|||
* Out: output: Pointer to a buffer of size strlen(hrp) + data_len + 8 that |
|||
* will be updated to contain the null-terminated Bech32 string. |
|||
* In: hrp : Pointer to the null-terminated human readable part. |
|||
* data : Pointer to an array of 5-bit values. |
|||
* data_len: Length of the data array. |
|||
* max_input_len: Maximum valid length of input (90 for segwit usage). |
|||
* enc: Which encoding to use (BECH32_ENCODING_BECH32{,M}). |
|||
* Returns 1 if successful. |
|||
*/ |
|||
int bech32_encode( |
|||
char *output, |
|||
const char *hrp, |
|||
const uint8_t *data, |
|||
size_t data_len, |
|||
size_t max_input_len, |
|||
bech32_encoding enc |
|||
); |
|||
|
|||
/** Decode a Bech32 or Bech32m string
|
|||
* |
|||
* Out: hrp: Pointer to a buffer of size strlen(input) - 6. Will be |
|||
* updated to contain the null-terminated human readable part. |
|||
* data: Pointer to a buffer of size strlen(input) - 8 that will |
|||
* hold the encoded 5-bit data values. |
|||
* data_len: Pointer to a size_t that will be updated to be the number |
|||
* of entries in data. |
|||
* In: input: Pointer to a null-terminated Bech32 string. |
|||
* max_input_len: Maximum valid length of input (90 for segwit usage). |
|||
* Returns BECH32_ENCODING_BECH32{,M} to indicate decoding was successful |
|||
* with the specified encoding standard. BECH32_ENCODING_NONE is returned if |
|||
* decoding failed. |
|||
*/ |
|||
bech32_encoding bech32_decode( |
|||
char *hrp, |
|||
uint8_t *data, |
|||
size_t *data_len, |
|||
const char *input, |
|||
size_t max_input_len |
|||
); |
|||
|
|||
/* Helper from bech32: translates inbits-bit bytes to outbits-bit bytes.
|
|||
* @outlen is incremented as bytes are added. |
|||
* @pad is true if we're to pad, otherwise truncate last byte if necessary |
|||
*/ |
|||
int bech32_convert_bits(uint8_t* out, size_t* outlen, int outbits, |
|||
const uint8_t* in, size_t inlen, int inbits, |
|||
int pad); |
|||
|
|||
/* The charset, and reverse mapping */ |
|||
extern const char bech32_charset[32]; |
|||
extern const int8_t bech32_charset_rev[128]; |
|||
|
|||
#endif /* LIGHTNING_COMMON_BECH32_H */ |
|||
|
@ -0,0 +1,127 @@ |
|||
#include "config.h" |
|||
#include "bech32.h" |
|||
#include "bech32_util.h" |
|||
#include "hash_u5.h" |
|||
#include "talstr.h" |
|||
#include "tal.h" |
|||
#include "short_types.h" |
|||
#include <stdbool.h> |
|||
|
|||
static u8 get_bit(const u8 *src, size_t bitoff) |
|||
{ |
|||
return ((src[bitoff / 8] >> (7 - (bitoff % 8))) & 1); |
|||
} |
|||
|
|||
void bech32_push_bits(u5 **data, const void *src, size_t nbits) |
|||
{ |
|||
size_t i, b; |
|||
size_t data_len = tal_count(*data); |
|||
|
|||
for (i = 0; i < nbits; i += b) { |
|||
tal_resize(data, data_len+1); |
|||
(*data)[data_len] = 0; |
|||
for (b = 0; b < 5; b++) { |
|||
(*data)[data_len] <<= 1; |
|||
/* If we need bits we don't have, zero */ |
|||
if (i+b < nbits) |
|||
(*data)[data_len] |= get_bit(src, i+b); |
|||
} |
|||
data_len++; |
|||
} |
|||
} |
|||
|
|||
static u8 get_u5_bit(const u5 *src, size_t bitoff) |
|||
{ |
|||
return ((src[bitoff / 5] >> (4 - (bitoff % 5))) & 1); |
|||
} |
|||
|
|||
void bech32_pull_bits(u8 **data, const u5 *src, size_t nbits) |
|||
{ |
|||
size_t i; |
|||
size_t data_len = tal_count(*data); |
|||
|
|||
/* We discard trailing bits. */ |
|||
for (i = 0; i + 8 <= nbits; i += 8) { |
|||
tal_resize(data, data_len+1); |
|||
(*data)[data_len] = 0; |
|||
for (size_t b = 0; b < 8; b++) { |
|||
(*data)[data_len] <<= 1; |
|||
(*data)[data_len] |= get_u5_bit(src, i+b); |
|||
} |
|||
data_len++; |
|||
} |
|||
} |
|||
|
|||
/* Returns a char, tracks case. */ |
|||
static int fixup_char(int c, bool *upper, bool *lower) |
|||
{ |
|||
if (c >= 'A' && c <= 'Z') { |
|||
*upper = true; |
|||
return c + ('a' - 'A'); |
|||
} else if (c >= 'a' && c <= 'z') { |
|||
*lower = true; |
|||
} |
|||
return c; |
|||
} |
|||
|
|||
bool from_bech32_charset(const tal_t *ctx, |
|||
const char *bech32, |
|||
size_t bech32_len, |
|||
char **hrp, u8 **data) |
|||
{ |
|||
u5 *u5data; |
|||
const char *sep; |
|||
bool upper = false, lower = false; |
|||
size_t datalen; |
|||
|
|||
sep = memchr(bech32, '1', bech32_len); |
|||
if (!sep) |
|||
return false; |
|||
|
|||
*hrp = tal_strndup(ctx, bech32, sep - bech32); |
|||
for (size_t i = 0; i < strlen(*hrp); i++) |
|||
(*hrp)[i] = fixup_char((*hrp)[i], &upper, &lower); |
|||
|
|||
datalen = bech32_len - (sep + 1 - bech32); |
|||
u5data = tal_arr(NULL, u5, datalen); |
|||
for (size_t i = 0; i < datalen; i++) { |
|||
int c = sep[1+i]; |
|||
if (c < 0 || c > 128) |
|||
goto fail; |
|||
c = fixup_char(c, &upper, &lower); |
|||
if (bech32_charset_rev[c] == -1) |
|||
goto fail; |
|||
u5data[i] = bech32_charset_rev[c]; |
|||
} |
|||
|
|||
/* Check case consistency */ |
|||
if (upper && lower) |
|||
goto fail; |
|||
|
|||
*data = tal_arr(ctx, u8, 0); |
|||
bech32_pull_bits(data, u5data, tal_bytelen(u5data) * 5); |
|||
tal_free(u5data); |
|||
return true; |
|||
|
|||
fail: |
|||
*hrp = tal_free(*hrp); |
|||
tal_free(u5data); |
|||
return false; |
|||
} |
|||
|
|||
char *to_bech32_charset(const tal_t *ctx, |
|||
const char *hrp, const u8 *data) |
|||
{ |
|||
u5 *u5data = tal_arr(NULL, u5, 0); |
|||
char *ret; |
|||
|
|||
bech32_push_bits(&u5data, data, tal_bytelen(data) * 8); |
|||
ret = tal_dup_arr(ctx, char, hrp, strlen(hrp), |
|||
1 + tal_bytelen(u5data) + 1); |
|||
ret[strlen(hrp)] = '1'; |
|||
for (size_t i = 0; i < tal_bytelen(u5data); i++) |
|||
ret[strlen(hrp) + 1 + i] = bech32_charset[u5data[i]]; |
|||
ret[strlen(hrp) + 1 + tal_bytelen(u5data)] = '\0'; |
|||
tal_free(u5data); |
|||
return ret; |
|||
} |
@ -0,0 +1,28 @@ |
|||
#ifndef LIGHTNING_COMMON_BECH32_UTIL_H |
|||
#define LIGHTNING_COMMON_BECH32_UTIL_H |
|||
#include "config.h" |
|||
|
|||
#include "tal.h" |
|||
#include "hash_u5.h" |
|||
|
|||
/**
|
|||
* Push the bytes in src in 5 bit format onto the end of data. |
|||
*/ |
|||
void bech32_push_bits(u5 **data, const void *src, size_t nbits); |
|||
|
|||
/**
|
|||
* Push the bytes in src in 8 bit format onto the end of data. |
|||
*/ |
|||
void bech32_pull_bits(u8 **data, const u5 *src, size_t nbits); |
|||
|
|||
/**
|
|||
* Checksumless bech32 routines. |
|||
*/ |
|||
bool from_bech32_charset(const tal_t *ctx, |
|||
const char *bech32, size_t bech32_len, |
|||
char **hrp, u8 **data); |
|||
|
|||
char *to_bech32_charset(const tal_t *ctx, |
|||
const char *hrp, const u8 *data); |
|||
|
|||
#endif /* LIGHTNING_COMMON_BECH32_UTIL_H */ |
@ -0,0 +1,676 @@ |
|||
//
|
|||
// bolt11.c
|
|||
// damus
|
|||
//
|
|||
// Created by William Casarin on 2022-10-18.
|
|||
//
|
|||
|
|||
#include "bolt11.h" |
|||
|
|||
//#include "address.h"
|
|||
//#include "script.h"
|
|||
#include "bech32.h" |
|||
#include "utf8.h" |
|||
#include "compiler.h" |
|||
#include "endian.h" |
|||
#include "list.h" |
|||
#include "talstr.h" |
|||
#include "tal.h" |
|||
#include "node_id.h" |
|||
#include "bech32_util.h" |
|||
#include "bolt11.h" |
|||
#include "amount.h" |
|||
#include "array_size.h" |
|||
#include "structeq.h" |
|||
|
|||
//#include "features.h"
|
|||
#include <errno.h> |
|||
#include <inttypes.h> |
|||
#include <assert.h> |
|||
|
|||
#define MSAT_PER_SAT ((u64)1000) |
|||
#define SAT_PER_BTC ((u64)100000000) |
|||
#define MSAT_PER_BTC (MSAT_PER_SAT * SAT_PER_BTC) |
|||
|
|||
struct multiplier { |
|||
const char letter; |
|||
/* We can't represent p postfix to msat, so we multiply this by 10 */ |
|||
u64 m10; |
|||
}; |
|||
|
|||
/* BOLT #11:
|
|||
* |
|||
* The following `multiplier` letters are defined: |
|||
* |
|||
* * `m` (milli): multiply by 0.001 |
|||
* * `u` (micro): multiply by 0.000001 |
|||
* * `n` (nano): multiply by 0.000000001 |
|||
* * `p` (pico): multiply by 0.000000000001 |
|||
*/ |
|||
static struct multiplier multipliers[] = { |
|||
{ 'm', 10 * MSAT_PER_BTC / 1000 }, |
|||
{ 'u', 10 * MSAT_PER_BTC / 1000000 }, |
|||
{ 'n', 10 * MSAT_PER_BTC / 1000000000 }, |
|||
{ 'p', 10 * MSAT_PER_BTC / 1000000000000ULL } |
|||
}; |
|||
|
|||
/* If pad is false, we discard any bits which don't fit in the last byte.
|
|||
* Otherwise we add an extra byte */ |
|||
static bool pull_bits(struct hash_u5 *hu5, |
|||
u5 **data, size_t *data_len, void *dst, size_t nbits, |
|||
bool pad) |
|||
{ |
|||
size_t n5 = nbits / 5; |
|||
size_t len = 0; |
|||
|
|||
if (nbits % 5) |
|||
n5++; |
|||
|
|||
if (*data_len < n5) |
|||
return false; |
|||
if (!bech32_convert_bits(dst, &len, 8, *data, n5, 5, pad)) |
|||
return false; |
|||
if (hu5) |
|||
hash_u5(hu5, *data, n5); |
|||
*data += n5; |
|||
*data_len -= n5; |
|||
|
|||
return true; |
|||
} |
|||
|
|||
/* For pulling fields where we should have checked it will succeed already. */ |
|||
#ifndef NDEBUG |
|||
#define pull_bits_certain(hu5, data, data_len, dst, nbits, pad) \ |
|||
assert(pull_bits((hu5), (data), (data_len), (dst), (nbits), (pad))) |
|||
#else |
|||
#define pull_bits_certain pull_bits |
|||
#endif |
|||
|
|||
/* Helper for pulling a variable-length big-endian int. */ |
|||
static bool pull_uint(struct hash_u5 *hu5, |
|||
u5 **data, size_t *data_len, |
|||
u64 *val, size_t databits) |
|||
{ |
|||
be64 be_val; |
|||
|
|||
/* Too big. */ |
|||
if (databits > sizeof(be_val) * CHAR_BIT) |
|||
return false; |
|||
if (!pull_bits(hu5, data, data_len, &be_val, databits, true)) |
|||
return false; |
|||
*val = be64_to_cpu(be_val) >> (sizeof(be_val) * CHAR_BIT - databits); |
|||
return true; |
|||
} |
|||
|
|||
static size_t num_u8(size_t num_u5) |
|||
{ |
|||
return (num_u5 * 5 + 4) / 8; |
|||
} |
|||
|
|||
/* Frees bolt11, returns NULL. */ |
|||
static struct bolt11 *decode_fail(struct bolt11 *b11, char **fail, |
|||
const char *fmt, ...) |
|||
PRINTF_FMT(3,4); |
|||
|
|||
static struct bolt11 *decode_fail(struct bolt11 *b11, char **fail, |
|||
const char *fmt, ...) |
|||
{ |
|||
va_list ap; |
|||
|
|||
va_start(ap, fmt); |
|||
*fail = tal_vfmt(tal_parent(b11), fmt, ap); |
|||
va_end(ap); |
|||
return tal_free(b11); |
|||
} |
|||
|
|||
/*
|
|||
* These handle specific fields in the payment request; returning the problem |
|||
* if any, or NULL. |
|||
*/ |
|||
static char *unknown_field(struct bolt11 *b11, |
|||
struct hash_u5 *hu5, |
|||
u5 **data, size_t *data_len, |
|||
u5 type, size_t length) |
|||
{ |
|||
struct bolt11_field *extra = tal(b11, struct bolt11_field); |
|||
u8 u8data[num_u8(length)]; |
|||
|
|||
extra->tag = type; |
|||
extra->data = tal_dup_arr(extra, u5, *data, length, 0); |
|||
list_add_tail(&b11->extra_fields, &extra->list); |
|||
|
|||
pull_bits_certain(hu5, data, data_len, u8data, length * 5, true); |
|||
return NULL; |
|||
} |
|||
|
|||
/* BOLT #11:
|
|||
* |
|||
* `p` (1): `data_length` 52. 256-bit SHA256 payment_hash. Preimage of this |
|||
* provides proof of payment |
|||
*/ |
|||
static void decode_p(struct bolt11 *b11, |
|||
struct hash_u5 *hu5, |
|||
u5 **data, size_t *data_len, |
|||
size_t data_length, bool *have_p) |
|||
{ |
|||
/* BOLT #11:
|
|||
* |
|||
* A payer... SHOULD use the first `p` field that it did NOT |
|||
* skip as the payment hash. |
|||
*/ |
|||
if (*have_p) { |
|||
unknown_field(b11, hu5, data, data_len, 'p', data_length); |
|||
return; |
|||
} |
|||
|
|||
/* BOLT #11:
|
|||
* |
|||
* A reader... MUST skip over unknown fields, OR an `f` field |
|||
* with unknown `version`, OR `p`, `h`, `s` or `n` fields that do |
|||
* NOT have `data_length`s of 52, 52, 52 or 53, respectively. |
|||
*/ |
|||
if (data_length != 52) { |
|||
unknown_field(b11, hu5, data, data_len, 'p', data_length); |
|||
return; |
|||
} |
|||
|
|||
pull_bits_certain(hu5, data, data_len, &b11->payment_hash, 256, false); |
|||
*have_p = true; |
|||
} |
|||
|
|||
|
|||
static char *utf8_str(const tal_t *ctx, const u8 *buf TAKES, size_t buflen) |
|||
{ |
|||
char *ret; |
|||
|
|||
if (!utf8_check(buf, buflen)) { |
|||
if (taken(buf)) |
|||
tal_free(buf); |
|||
return NULL; |
|||
} |
|||
|
|||
/* Add one for nul term */ |
|||
ret = tal_dup_arr(ctx, char, (const char *)buf, buflen, 1); |
|||
ret[buflen] = '\0'; |
|||
return ret; |
|||
} |
|||
|
|||
|
|||
/* BOLT #11:
|
|||
* |
|||
* `d` (13): `data_length` variable. Short description of purpose of payment |
|||
* (UTF-8), e.g. '1 cup of coffee' or 'ナンセンス 1杯' |
|||
*/ |
|||
static char *decode_d(struct bolt11 *b11, |
|||
struct hash_u5 *hu5, |
|||
u5 **data, size_t *data_len, |
|||
size_t data_length, bool *have_d) |
|||
{ |
|||
u8 *desc; |
|||
if (*have_d) |
|||
return unknown_field(b11, hu5, data, data_len, 'd', data_length); |
|||
|
|||
desc = tal_arr(NULL, u8, data_length * 5 / 8); |
|||
pull_bits_certain(hu5, data, data_len, desc, data_length*5, false); |
|||
|
|||
*have_d = true; |
|||
b11->description = utf8_str(b11, take(desc), tal_bytelen(desc)); |
|||
if (b11->description) |
|||
return NULL; |
|||
|
|||
return tal_fmt(b11, "d: invalid utf8"); |
|||
} |
|||
|
|||
/* BOLT #11:
|
|||
* |
|||
* `h` (23): `data_length` 52. 256-bit description of purpose of payment |
|||
* (SHA256). This is used to commit to an associated description that is over |
|||
* 639 bytes, but the transport mechanism for the description in that case is |
|||
* transport specific and not defined here. |
|||
*/ |
|||
static void decode_h(struct bolt11 *b11, |
|||
struct hash_u5 *hu5, |
|||
u5 **data, size_t *data_len, |
|||
size_t data_length, bool *have_h) |
|||
{ |
|||
if (*have_h) { |
|||
unknown_field(b11, hu5, data, data_len, 'h', data_length); |
|||
return; |
|||
} |
|||
|
|||
/* BOLT #11:
|
|||
* |
|||
* A reader... MUST skip over unknown fields, OR an `f` field |
|||
* with unknown `version`, OR `p`, `h`, `s` or `n` fields that do |
|||
* NOT have `data_length`s of 52, 52, 52 or 53, respectively. */ |
|||
if (data_length != 52) { |
|||
unknown_field(b11, hu5, data, data_len, 'h', data_length); |
|||
return; |
|||
} |
|||
|
|||
b11->description_hash = tal(b11, struct sha256); |
|||
pull_bits_certain(hu5, data, data_len, b11->description_hash, 256, |
|||
false); |
|||
*have_h = true; |
|||
} |
|||
|
|||
/* BOLT #11:
|
|||
* |
|||
* `x` (6): `data_length` variable. `expiry` time in seconds |
|||
* (big-endian). Default is 3600 (1 hour) if not specified. |
|||
*/ |
|||
#define DEFAULT_X 3600 |
|||
static char *decode_x(struct bolt11 *b11, |
|||
struct hash_u5 *hu5, |
|||
u5 **data, size_t *data_len, |
|||
size_t data_length, bool *have_x) |
|||
{ |
|||
if (*have_x) |
|||
return unknown_field(b11, hu5, data, data_len, 'x', |
|||
data_length); |
|||
|
|||
/* FIXME: Put upper limit in bolt 11 */ |
|||
if (!pull_uint(hu5, data, data_len, &b11->expiry, data_length * 5)) |
|||
return tal_fmt(b11, "x: length %zu chars is excessive", |
|||
*data_len); |
|||
|
|||
*have_x = true; |
|||
return NULL; |
|||
} |
|||
|
|||
/* BOLT #11:
|
|||
* |
|||
* `c` (24): `data_length` variable. `min_final_cltv_expiry` to use for the |
|||
* last HTLC in the route. Default is 18 if not specified. |
|||
*/ |
|||
static char *decode_c(struct bolt11 *b11, |
|||
struct hash_u5 *hu5, |
|||
u5 **data, size_t *data_len, |
|||
size_t data_length, bool *have_c) |
|||
{ |
|||
u64 c; |
|||
if (*have_c) |
|||
return unknown_field(b11, hu5, data, data_len, 'c', |
|||
data_length); |
|||
|
|||
/* FIXME: Put upper limit in bolt 11 */ |
|||
if (!pull_uint(hu5, data, data_len, &c, data_length * 5)) |
|||
return tal_fmt(b11, "c: length %zu chars is excessive", |
|||
*data_len); |
|||
b11->min_final_cltv_expiry = c; |
|||
/* Can overflow, since c is 64 bits but value must be < 32 bits */ |
|||
if (b11->min_final_cltv_expiry != c) |
|||
return tal_fmt(b11, "c: %"PRIu64" is too large", c); |
|||
|
|||
*have_c = true; |
|||
return NULL; |
|||
} |
|||
|
|||
static char *decode_n(struct bolt11 *b11, |
|||
struct hash_u5 *hu5, |
|||
u5 **data, size_t *data_len, |
|||
size_t data_length, bool *have_n) |
|||
{ |
|||
if (*have_n) |
|||
return unknown_field(b11, hu5, data, data_len, 'n', |
|||
data_length); |
|||
|
|||
/* BOLT #11:
|
|||
* |
|||
* A reader... MUST skip over unknown fields, OR an `f` field |
|||
* with unknown `version`, OR `p`, `h`, `s` or `n` fields that do |
|||
* NOT have `data_length`s of 52, 52, 52 or 53, respectively. */ |
|||
if (data_length != 53) |
|||
return unknown_field(b11, hu5, data, data_len, 'n', |
|||
data_length); |
|||
|
|||
pull_bits_certain(hu5, data, data_len, &b11->receiver_id.k, |
|||
data_length * 5, false); |
|||
/*
|
|||
if (!node_id_valid(&b11->receiver_id)) |
|||
return tal_fmt(b11, "n: invalid pubkey %s", |
|||
node_id_to_hexstr(b11, &b11->receiver_id)); |
|||
*/ |
|||
|
|||
*have_n = true; |
|||
return NULL; |
|||
} |
|||
|
|||
/* BOLT #11:
|
|||
* |
|||
* `m` (27): `data_length` variable. Additional metadata to attach to |
|||
* the payment. Note that the size of this field is limited by the |
|||
* maximum hop payload size. Long metadata fields reduce the maximum |
|||
* route length. |
|||
*/ |
|||
static char *decode_m(struct bolt11 *b11, |
|||
struct hash_u5 *hu5, |
|||
u5 **data, size_t *data_len, |
|||
size_t data_length, |
|||
bool *have_m) |
|||
{ |
|||
size_t mlen = (data_length * 5) / 8; |
|||
|
|||
if (*have_m) |
|||
return unknown_field(b11, hu5, data, data_len, 'm', |
|||
data_length); |
|||
|
|||
b11->metadata = tal_arr(b11, u8, mlen); |
|||
pull_bits_certain(hu5, data, data_len, b11->metadata, |
|||
data_length * 5, false); |
|||
|
|||
*have_m = true; |
|||
return NULL; |
|||
} |
|||
|
|||
struct bolt11 *new_bolt11(const tal_t *ctx) |
|||
{ |
|||
struct bolt11 *b11 = tal(ctx, struct bolt11); |
|||
|
|||
list_head_init(&b11->extra_fields); |
|||
b11->description = NULL; |
|||
b11->description_hash = NULL; |
|||
b11->fallbacks = NULL; |
|||
b11->msat = NULL; |
|||
b11->expiry = DEFAULT_X; |
|||
b11->features = tal_arr(b11, u8, 0); |
|||
/* BOLT #11:
|
|||
* - if the `c` field (`min_final_cltv_expiry`) is not provided: |
|||
* - MUST use an expiry delta of at least 18 when making the payment |
|||
*/ |
|||
b11->min_final_cltv_expiry = 18; |
|||
//b11->payment_secret = NULL;
|
|||
b11->metadata = NULL; |
|||
|
|||
//if (msat)
|
|||
//b11->msat = tal_dup(b11, struct amount_msat, msat);
|
|||
return b11; |
|||
} |
|||
|
|||
/* Define sha256_eq. */ |
|||
//STRUCTEQ_DEF(sha256, 0, u);
|
|||
|
|||
/* Extracts signature but does not check it. */ |
|||
struct bolt11 *bolt11_decode_nosig(const tal_t *ctx, const char *str, u5 **sig, char **fail) |
|||
{ |
|||
char *hrp, *amountstr, *prefix; |
|||
u5 *data; |
|||
size_t data_len; |
|||
struct bolt11 *b11 = new_bolt11(ctx); |
|||
struct hash_u5 hu5; |
|||
bool have_p = false, have_d = false, have_h = false, have_n = false, |
|||
have_x = false, have_c = false, have_m = false; |
|||
|
|||
/* BOLT #11:
|
|||
* |
|||
* If a URI scheme is desired, the current recommendation is to either |
|||
* use 'lightning:' as a prefix before the BOLT-11 encoding |
|||
*/ |
|||
if (strstarts(str, "lightning:") || strstarts(str, "LIGHTNING:")) |
|||
str += strlen("lightning:"); |
|||
|
|||
if (strlen(str) < 8) |
|||
return decode_fail(b11, fail, "Bad bech32 string"); |
|||
|
|||
hrp = tal_arr(b11, char, strlen(str) - 6); |
|||
data = tal_arr(b11, u5, strlen(str) - 8); |
|||
|
|||
if (bech32_decode(hrp, data, &data_len, str, (size_t)-1) |
|||
!= BECH32_ENCODING_BECH32) |
|||
return decode_fail(b11, fail, "Bad bech32 string"); |
|||
|
|||
/* For signature checking at the end. */ |
|||
hash_u5_init(&hu5, hrp); |
|||
|
|||
/* BOLT #11:
|
|||
* |
|||
* The human-readable part of a Lightning invoice consists of two sections: |
|||
* 1. `prefix`: `ln` + BIP-0173 currency prefix (e.g. `lnbc` for Bitcoin mainnet, |
|||
* `lntb` for Bitcoin testnet, `lntbs` for Bitcoin signet, and `lnbcrt` for Bitcoin regtest) |
|||
* 1. `amount`: optional number in that currency, followed by an optional |
|||
* `multiplier` letter. The unit encoded here is the 'social' convention of a payment unit -- in the case of Bitcoin the unit is 'bitcoin' NOT satoshis. |
|||
*/ |
|||
prefix = tal_strndup(b11, hrp, strcspn(hrp, "0123456789")); |
|||
|
|||
/* BOLT #11:
|
|||
* |
|||
* A reader...if it does NOT understand the `prefix`... MUST fail the payment. |
|||
*/ |
|||
if (!strstarts(prefix, "ln")) |
|||
return decode_fail(b11, fail, |
|||
"Prefix '%s' does not start with ln", prefix); |
|||
|
|||
/* BOLT #11:
|
|||
* |
|||
* - if the `amount` is empty: |
|||
* */ |
|||
amountstr = tal_strdup(b11, hrp + strlen(prefix)); |
|||
if (streq(amountstr, "")) { |
|||
/* BOLT #11:
|
|||
* |
|||
* - SHOULD indicate to the payer that amount is unspecified. |
|||
*/ |
|||
b11->msat = NULL; |
|||
} else { |
|||
u64 m10 = 10 * MSAT_PER_BTC; /* Pico satoshis in a Bitcoin */ |
|||
u64 amount; |
|||
char *end; |
|||
|
|||
/* Gather and trim multiplier */ |
|||
end = amountstr + strlen(amountstr)-1; |
|||
for (size_t i = 0; i < ARRAY_SIZE(multipliers); i++) { |
|||
if (*end == multipliers[i].letter) { |
|||
m10 = multipliers[i].m10; |
|||
*end = '\0'; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
/* BOLT #11:
|
|||
* |
|||
* if `amount` contains a non-digit OR is followed by |
|||
* anything except a `multiplier` (see table above)... MUST fail the |
|||
* payment. |
|||
**/ |
|||
amount = strtoull(amountstr, &end, 10); |
|||
if (amount == ULLONG_MAX && errno == ERANGE) |
|||
return decode_fail(b11, fail, |
|||
"Invalid amount '%s'", amountstr); |
|||
if (!*amountstr || *end) |
|||
return decode_fail(b11, fail, |
|||
"Invalid amount postfix '%s'", end); |
|||
|
|||
/* BOLT #11:
|
|||
* |
|||
* if the `multiplier` is present... MUST multiply |
|||
* `amount` by the `multiplier` value to derive the |
|||
* amount required for payment. |
|||
*/ |
|||
b11->msat = tal(b11, struct amount_msat); |
|||
/* BOLT #11:
|
|||
* |
|||
* - if multiplier is `p` and the last decimal of `amount` is |
|||
* not 0: |
|||
* - MUST fail the payment. |
|||
*/ |
|||
if (amount * m10 % 10 != 0) |
|||
return decode_fail(b11, fail, |
|||
"Invalid sub-millisatoshi amount" |
|||
" '%sp'", amountstr); |
|||
|
|||
*b11->msat = amount_msat(amount * m10 / 10); |
|||
} |
|||
|
|||
/* BOLT #11:
|
|||
* |
|||
* The data part of a Lightning invoice consists of multiple sections: |
|||
* |
|||
* 1. `timestamp`: seconds-since-1970 (35 bits, big-endian) |
|||
* 1. zero or more tagged parts |
|||
* 1. `signature`: Bitcoin-style signature of above (520 bits) |
|||
*/ |
|||
if (!pull_uint(&hu5, &data, &data_len, &b11->timestamp, 35)) |
|||
return decode_fail(b11, fail, "Can't get 35-bit timestamp"); |
|||
|
|||
while (data_len > 520 / 5) { |
|||
const char *problem = NULL; |
|||
u64 type, data_length; |
|||
|
|||
/* BOLT #11:
|
|||
* |
|||
* Each Tagged Field is of the form: |
|||
* |
|||
* 1. `type` (5 bits) |
|||
* 1. `data_length` (10 bits, big-endian) |
|||
* 1. `data` (`data_length` x 5 bits) |
|||
*/ |
|||
if (!pull_uint(&hu5, &data, &data_len, &type, 5) |
|||
|| !pull_uint(&hu5, &data, &data_len, &data_length, 10)) |
|||
return decode_fail(b11, fail, |
|||
"Can't get tag and length"); |
|||
|
|||
/* Can't exceed total data remaining. */ |
|||
if (data_length > data_len) |
|||
return decode_fail(b11, fail, "%c: truncated", |
|||
bech32_charset[type]); |
|||
|
|||
switch (bech32_charset[type]) { |
|||
case 'p': |
|||
decode_p(b11, &hu5, &data, &data_len, data_length, |
|||
&have_p); |
|||
break; |
|||
|
|||
case 'd': |
|||
problem = decode_d(b11, &hu5, &data, &data_len, |
|||
data_length, &have_d); |
|||
break; |
|||
|
|||
case 'h': |
|||
decode_h(b11, &hu5, &data, &data_len, data_length, |
|||
&have_h); |
|||
break; |
|||
|
|||
case 'n': |
|||
problem = decode_n(b11, &hu5, &data, |
|||
&data_len, data_length, |
|||
have_n); |
|||
break; |
|||
|
|||
case 'x': |
|||
problem = decode_x(b11, &hu5, &data, |
|||
&data_len, data_length, |
|||
&have_x); |
|||
break; |
|||
|
|||
case 'c': |
|||
problem = decode_c(b11, &hu5, &data, |
|||
&data_len, data_length, |
|||
&have_c); |
|||
break; |
|||
|
|||
/*
|
|||
case 'f': |
|||
problem = decode_f(b11, &hu5, &data, |
|||
&data_len, data_length); |
|||
break; |
|||
case 'r': |
|||
problem = decode_r(b11, &hu5, &data, &data_len, |
|||
data_length); |
|||
break; |
|||
case '9': |
|||
problem = decode_9(b11, our_features, &hu5, |
|||
&data, &data_len, |
|||
data_length); |
|||
break; |
|||
case 's': |
|||
problem = decode_s(b11, &hu5, &data, &data_len, |
|||
data_length, &have_s); |
|||
break; |
|||
*/ |
|||
case 'm': |
|||
problem = decode_m(b11, &hu5, &data, &data_len, |
|||
data_length, &have_m); |
|||
break; |
|||
default: |
|||
unknown_field(b11, &hu5, &data, &data_len, |
|||
bech32_charset[type], data_length); |
|||
} |
|||
if (problem) |
|||
return decode_fail(b11, fail, "%s", problem); |
|||
} |
|||
|
|||
if (!have_p) |
|||
return decode_fail(b11, fail, "No valid 'p' field found"); |
|||
|
|||
*sig = tal_dup_arr(ctx, u5, data, data_len, 0); |
|||
return b11; |
|||
} |
|||
|
|||
/* Decodes and checks signature; returns NULL on error. */ |
|||
struct bolt11 *bolt11_decode(const tal_t *ctx, const char *str, char **fail) |
|||
{ |
|||
u5 *sigdata; |
|||
size_t data_len; |
|||
u8 sig_and_recid[65]; |
|||
//secp256k1_ecdsa_recoverable_signature sig;
|
|||
struct bolt11 *b11; |
|||
|
|||
b11 = bolt11_decode_nosig(ctx, str, &sigdata, fail); |
|||
if (!b11) |
|||
return NULL; |
|||
|
|||
/* BOLT #11:
|
|||
* |
|||
* A writer...MUST set `signature` to a valid 512-bit |
|||
* secp256k1 signature of the SHA2 256-bit hash of the |
|||
* human-readable part, represented as UTF-8 bytes, |
|||
* concatenated with the data part (excluding the signature) |
|||
* with 0 bits appended to pad the data to the next byte |
|||
* boundary, with a trailing byte containing the recovery ID |
|||
* (0, 1, 2, or 3). |
|||
*/ |
|||
data_len = tal_count(sigdata); |
|||
if (!pull_bits(NULL, &sigdata, &data_len, sig_and_recid, 520, false)) |
|||
return decode_fail(b11, fail, "signature truncated"); |
|||
|
|||
assert(data_len == 0); |
|||
|
|||
/*
|
|||
if (!secp256k1_ecdsa_recoverable_signature_parse_compact |
|||
(secp256k1_ctx, &sig, sig_and_recid, sig_and_recid[64])) |
|||
return decode_fail(b11, fail, "signature invalid"); |
|||
|
|||
secp256k1_ecdsa_recoverable_signature_convert(secp256k1_ctx, |
|||
&b11->sig, &sig); |
|||
*/ |
|||
|
|||
/* BOLT #11:
|
|||
* |
|||
* A reader... MUST check that the `signature` is valid (see |
|||
* the `n` tagged field specified below). ... A reader... |
|||
* MUST use the `n` field to validate the signature instead of |
|||
* performing signature recovery. |
|||
*/ |
|||
/*
|
|||
if (!have_n) { |
|||
struct pubkey k; |
|||
if (!secp256k1_ecdsa_recover(secp256k1_ctx, |
|||
&k.pubkey, |
|||
&sig, |
|||
(const u8 *)&hash)) |
|||
return decode_fail(b11, fail, |
|||
"signature recovery failed"); |
|||
node_id_from_pubkey(&b11->receiver_id, &k); |
|||
} else { |
|||
struct pubkey k; |
|||
if (!pubkey_from_node_id(&k, &b11->receiver_id)) |
|||
abort(); |
|||
if (!secp256k1_ecdsa_verify(secp256k1_ctx, &b11->sig, |
|||
(const u8 *)&hash, |
|||
&k.pubkey)) |
|||
return decode_fail(b11, fail, "invalid signature"); |
|||
} |
|||
*/ |
|||
|
|||
return b11; |
|||
} |
@ -0,0 +1,104 @@ |
|||
#ifndef LIGHTNING_COMMON_BOLT11_H |
|||
#define LIGHTNING_COMMON_BOLT11_H |
|||
|
|||
#include "short_types.h" |
|||
#include "hash_u5.h" |
|||
#include "list.h" |
|||
#include "node_id.h" |
|||
//#include <secp256k1_recovery.h>
|
|||
|
|||
/* We only have 10 bits for the field length, meaning < 640 bytes */ |
|||
#define BOLT11_FIELD_BYTE_LIMIT ((1 << 10) * 5 / 8) |
|||
|
|||
/* BOLT #11:
|
|||
* * `c` (24): `data_length` variable. |
|||
* `min_final_cltv_expiry` to use for the last HTLC in the route. |
|||
* Default is 18 if not specified. |
|||
*/ |
|||
#define DEFAULT_FINAL_CLTV_DELTA 18 |
|||
|
|||
struct feature_set; |
|||
|
|||
struct bolt11_field { |
|||
struct list_node list; |
|||
|
|||
char tag; |
|||
u5 *data; |
|||
}; |
|||
|
|||
/* BOLT #11:
|
|||
* * `pubkey` (264 bits) |
|||
* * `short_channel_id` (64 bits) |
|||
* * `fee_base_msat` (32 bits, big-endian) |
|||
* * `fee_proportional_millionths` (32 bits, big-endian) |
|||
* * `cltv_expiry_delta` (16 bits, big-endian) |
|||
*/ |
|||
|
|||
/*
|
|||
struct route_info { |
|||
struct node_id pubkey; |
|||
u16 cltv_expiry_delta; |
|||
struct short_channel_id short_channel_id; |
|||
u32 fee_base_msat, fee_proportional_millionths; |
|||
}; |
|||
*/ |
|||
|
|||
struct bolt11 { |
|||
const struct chainparams *chain; |
|||
u64 timestamp; |
|||
struct amount_msat *msat; /* NULL if not specified. */ |
|||
|
|||
struct sha256 payment_hash; |
|||
struct node_id receiver_id; |
|||
|
|||
/* description_hash valid if and only if description is NULL. */ |
|||
const char *description; |
|||
struct sha256 *description_hash; |
|||
|
|||
/* How many seconds to pay from @timestamp above. */ |
|||
u64 expiry; |
|||
|
|||
/* How many blocks final hop requires. */ |
|||
u32 min_final_cltv_expiry; |
|||
|
|||
/* If non-NULL, indicates fallback addresses to pay to. */ |
|||
const u8 **fallbacks; |
|||
|
|||
/* If non-NULL: array of route arrays */ |
|||
//struct route_info **routes;
|
|||
|
|||
/* signature of sha256 of entire thing. */ |
|||
//secp256k1_ecdsa_signature sig;
|
|||
|
|||
/* payment secret, if any. */ |
|||
//struct secret *payment_secret;
|
|||
|
|||
/* Features bitmap, if any. */ |
|||
u8 *features; |
|||
|
|||
/* Optional metadata to send with payment. */ |
|||
u8 *metadata; |
|||
|
|||
struct list_head extra_fields; |
|||
}; |
|||
|
|||
/* Decodes and checks signature; returns NULL on error; description is
|
|||
* (optional) out-of-band description of payment, for `h` field. |
|||
* fset is NULL to accept any features (usually not desirable!). |
|||
* |
|||
* if @must_be_chain is not NULL, fails unless it's this chain. |
|||
*/ |
|||
struct bolt11 *bolt11_decode(const tal_t *ctx, const char *str, char **fail); |
|||
|
|||
/* Extracts signature but does not check it. */ |
|||
struct bolt11 *bolt11_decode_nosig(const tal_t *ctx, const char *str, u5 **sigdata, char **fail); |
|||
|
|||
/* Initialize an empty bolt11 struct with optional amount */ |
|||
struct bolt11 *new_bolt11(const tal_t *ctx); |
|||
|
|||
#if DEVELOPER |
|||
/* Flag for tests to suppress `min_final_cltv_expiry` field generation, to match test vectors */ |
|||
extern bool dev_bolt11_no_c_generation; |
|||
#endif |
|||
|
|||
#endif /* LIGHTNING_COMMON_BOLT11_H */ |
@ -0,0 +1,40 @@ |
|||
/* CC0 (Public domain) - see LICENSE file for details */ |
|||
#ifndef CCAN_BUILD_ASSERT_H |
|||
#define CCAN_BUILD_ASSERT_H |
|||
|
|||
/**
|
|||
* BUILD_ASSERT - assert a build-time dependency. |
|||
* @cond: the compile-time condition which must be true. |
|||
* |
|||
* Your compile will fail if the condition isn't true, or can't be evaluated |
|||
* by the compiler. This can only be used within a function. |
|||
* |
|||
* Example: |
|||
* #include <stddef.h> |
|||
* ... |
|||
* static char *foo_to_char(struct foo *foo) |
|||
* { |
|||
* // This code needs string to be at start of foo.
|
|||
* BUILD_ASSERT(offsetof(struct foo, string) == 0); |
|||
* return (char *)foo; |
|||
* } |
|||
*/ |
|||
#define BUILD_ASSERT(cond) \ |
|||
do { (void) sizeof(char [1 - 2*!(cond)]); } while(0) |
|||
|
|||
/**
|
|||
* BUILD_ASSERT_OR_ZERO - assert a build-time dependency, as an expression. |
|||
* @cond: the compile-time condition which must be true. |
|||
* |
|||
* Your compile will fail if the condition isn't true, or can't be evaluated |
|||
* by the compiler. This can be used in an expression: its value is "0". |
|||
* |
|||
* Example: |
|||
* #define foo_to_char(foo) \ |
|||
* ((char *)(foo) \ |
|||
* + BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0)) |
|||
*/ |
|||
#define BUILD_ASSERT_OR_ZERO(cond) \ |
|||
(sizeof(char [1 - 2*!(cond)]) - 1) |
|||
|
|||
#endif /* CCAN_BUILD_ASSERT_H */ |
@ -0,0 +1,64 @@ |
|||
/* CC0 (Public domain) - see LICENSE file for details */ |
|||
#ifndef CCAN_CHECK_TYPE_H |
|||
#define CCAN_CHECK_TYPE_H |
|||
#include "config.h" |
|||
|
|||
/**
|
|||
* check_type - issue a warning or build failure if type is not correct. |
|||
* @expr: the expression whose type we should check (not evaluated). |
|||
* @type: the exact type we expect the expression to be. |
|||
* |
|||
* This macro is usually used within other macros to try to ensure that a macro |
|||
* argument is of the expected type. No type promotion of the expression is |
|||
* done: an unsigned int is not the same as an int! |
|||
* |
|||
* check_type() always evaluates to 0. |
|||
* |
|||
* If your compiler does not support typeof, then the best we can do is fail |
|||
* to compile if the sizes of the types are unequal (a less complete check). |
|||
* |
|||
* Example: |
|||
* // They should always pass a 64-bit value to _set_some_value!
|
|||
* #define set_some_value(expr) \ |
|||
* _set_some_value((check_type((expr), uint64_t), (expr))) |
|||
*/ |
|||
|
|||
/**
|
|||
* check_types_match - issue a warning or build failure if types are not same. |
|||
* @expr1: the first expression (not evaluated). |
|||
* @expr2: the second expression (not evaluated). |
|||
* |
|||
* This macro is usually used within other macros to try to ensure that |
|||
* arguments are of identical types. No type promotion of the expressions is |
|||
* done: an unsigned int is not the same as an int! |
|||
* |
|||
* check_types_match() always evaluates to 0. |
|||
* |
|||
* If your compiler does not support typeof, then the best we can do is fail |
|||
* to compile if the sizes of the types are unequal (a less complete check). |
|||
* |
|||
* Example: |
|||
* // Do subtraction to get to enclosing type, but make sure that
|
|||
* // pointer is of correct type for that member.
|
|||
* #define container_of(mbr_ptr, encl_type, mbr) \ |
|||
* (check_types_match((mbr_ptr), &((encl_type *)0)->mbr), \ |
|||
* ((encl_type *) \ |
|||
* ((char *)(mbr_ptr) - offsetof(encl_type, mbr)))) |
|||
*/ |
|||
#if HAVE_TYPEOF |
|||
#define check_type(expr, type) \ |
|||
((typeof(expr) *)0 != (type *)0) |
|||
|
|||
#define check_types_match(expr1, expr2) \ |
|||
((typeof(expr1) *)0 != (typeof(expr2) *)0) |
|||
#else |
|||
#include <ccan/build_assert/build_assert.h> |
|||
/* Without typeof, we can only test the sizes. */ |
|||
#define check_type(expr, type) \ |
|||
BUILD_ASSERT_OR_ZERO(sizeof(expr) == sizeof(type)) |
|||
|
|||
#define check_types_match(expr1, expr2) \ |
|||
BUILD_ASSERT_OR_ZERO(sizeof(expr1) == sizeof(expr2)) |
|||
#endif /* HAVE_TYPEOF */ |
|||
|
|||
#endif /* CCAN_CHECK_TYPE_H */ |
@ -0,0 +1,317 @@ |
|||
/* CC0 (Public domain) - see LICENSE file for details */ |
|||
#ifndef CCAN_COMPILER_H |
|||
#define CCAN_COMPILER_H |
|||
#include "config.h" |
|||
|
|||
#ifndef COLD |
|||
#if HAVE_ATTRIBUTE_COLD |
|||
/**
|
|||
* COLD - a function is unlikely to be called. |
|||
* |
|||
* Used to mark an unlikely code path and optimize appropriately. |
|||
* It is usually used on logging or error routines. |
|||
* |
|||
* Example: |
|||
* static void COLD moan(const char *reason) |
|||
* { |
|||
* fprintf(stderr, "Error: %s (%s)\n", reason, strerror(errno)); |
|||
* } |
|||
*/ |
|||
#define COLD __attribute__((__cold__)) |
|||
#else |
|||
#define COLD |
|||
#endif |
|||
#endif |
|||
|
|||
#ifndef NORETURN |
|||
#if HAVE_ATTRIBUTE_NORETURN |
|||
/**
|
|||
* NORETURN - a function does not return |
|||
* |
|||
* Used to mark a function which exits; useful for suppressing warnings. |
|||
* |
|||
* Example: |
|||
* static void NORETURN fail(const char *reason) |
|||
* { |
|||
* fprintf(stderr, "Error: %s (%s)\n", reason, strerror(errno)); |
|||
* exit(1); |
|||
* } |
|||
*/ |
|||
#define NORETURN __attribute__((__noreturn__)) |
|||
#else |
|||
#define NORETURN |
|||
#endif |
|||
#endif |
|||
|
|||
#ifndef PRINTF_FMT |
|||
#if HAVE_ATTRIBUTE_PRINTF |
|||
/**
|
|||
* PRINTF_FMT - a function takes printf-style arguments |
|||
* @nfmt: the 1-based number of the function's format argument. |
|||
* @narg: the 1-based number of the function's first variable argument. |
|||
* |
|||
* This allows the compiler to check your parameters as it does for printf(). |
|||
* |
|||
* Example: |
|||
* void PRINTF_FMT(2,3) my_printf(const char *prefix, const char *fmt, ...); |
|||
*/ |
|||
#define PRINTF_FMT(nfmt, narg) \ |
|||
__attribute__((format(__printf__, nfmt, narg))) |
|||
#else |
|||
#define PRINTF_FMT(nfmt, narg) |
|||
#endif |
|||
#endif |
|||
|
|||
#ifndef CONST_FUNCTION |
|||
#if HAVE_ATTRIBUTE_CONST |
|||
/**
|
|||
* CONST_FUNCTION - a function's return depends only on its argument |
|||
* |
|||
* This allows the compiler to assume that the function will return the exact |
|||
* same value for the exact same arguments. This implies that the function |
|||
* must not use global variables, or dereference pointer arguments. |
|||
*/ |
|||
#define CONST_FUNCTION __attribute__((__const__)) |
|||
#else |
|||
#define CONST_FUNCTION |
|||
#endif |
|||
|
|||
#ifndef PURE_FUNCTION |
|||
#if HAVE_ATTRIBUTE_PURE |
|||
/**
|
|||
* PURE_FUNCTION - a function is pure |
|||
* |
|||
* A pure function is one that has no side effects other than it's return value |
|||
* and uses no inputs other than it's arguments and global variables. |
|||
*/ |
|||
#define PURE_FUNCTION __attribute__((__pure__)) |
|||
#else |
|||
#define PURE_FUNCTION |
|||
#endif |
|||
#endif |
|||
#endif |
|||
|
|||
#if HAVE_ATTRIBUTE_UNUSED |
|||
#ifndef UNNEEDED |
|||
/**
|
|||
* UNNEEDED - a variable/function may not be needed |
|||
* |
|||
* This suppresses warnings about unused variables or functions, but tells |
|||
* the compiler that if it is unused it need not emit it into the source code. |
|||
* |
|||
* Example: |
|||
* // With some preprocessor options, this is unnecessary.
|
|||
* static UNNEEDED int counter; |
|||
* |
|||
* // With some preprocessor options, this is unnecessary.
|
|||
* static UNNEEDED void add_to_counter(int add) |
|||
* { |
|||
* counter += add; |
|||
* } |
|||
*/ |
|||
#define UNNEEDED __attribute__((__unused__)) |
|||
#endif |
|||
|
|||
#ifndef NEEDED |
|||
#if HAVE_ATTRIBUTE_USED |
|||
/**
|
|||
* NEEDED - a variable/function is needed |
|||
* |
|||
* This suppresses warnings about unused variables or functions, but tells |
|||
* the compiler that it must exist even if it (seems) unused. |
|||
* |
|||
* Example: |
|||
* // Even if this is unused, these are vital for debugging.
|
|||
* static NEEDED int counter; |
|||
* static NEEDED void dump_counter(void) |
|||
* { |
|||
* printf("Counter is %i\n", counter); |
|||
* } |
|||
*/ |
|||
#define NEEDED __attribute__((__used__)) |
|||
#else |
|||
/* Before used, unused functions and vars were always emitted. */ |
|||
#define NEEDED __attribute__((__unused__)) |
|||
#endif |
|||
#endif |
|||
|
|||
#ifndef UNUSED |
|||
/**
|
|||
* UNUSED - a parameter is unused |
|||
* |
|||
* Some compilers (eg. gcc with -W or -Wunused) warn about unused |
|||
* function parameters. This suppresses such warnings and indicates |
|||
* to the reader that it's deliberate. |
|||
* |
|||
* Example: |
|||
* // This is used as a callback, so needs to have this prototype.
|
|||
* static int some_callback(void *unused UNUSED) |
|||
* { |
|||
* return 0; |
|||
* } |
|||
*/ |
|||
#define UNUSED __attribute__((__unused__)) |
|||
#endif |
|||
#else |
|||
#ifndef UNNEEDED |
|||
#define UNNEEDED |
|||
#endif |
|||
#ifndef NEEDED |
|||
#define NEEDED |
|||
#endif |
|||
#ifndef UNUSED |
|||
#define UNUSED |
|||
#endif |
|||
#endif |
|||
|
|||
#ifndef IS_COMPILE_CONSTANT |
|||
#if HAVE_BUILTIN_CONSTANT_P |
|||
/**
|
|||
* IS_COMPILE_CONSTANT - does the compiler know the value of this expression? |
|||
* @expr: the expression to evaluate |
|||
* |
|||
* When an expression manipulation is complicated, it is usually better to |
|||
* implement it in a function. However, if the expression being manipulated is |
|||
* known at compile time, it is better to have the compiler see the entire |
|||
* expression so it can simply substitute the result. |
|||
* |
|||
* This can be done using the IS_COMPILE_CONSTANT() macro. |
|||
* |
|||
* Example: |
|||
* enum greek { ALPHA, BETA, GAMMA, DELTA, EPSILON }; |
|||
* |
|||
* // Out-of-line version.
|
|||
* const char *greek_name(enum greek greek); |
|||
* |
|||
* // Inline version.
|
|||
* static inline const char *_greek_name(enum greek greek) |
|||
* { |
|||
* switch (greek) { |
|||
* case ALPHA: return "alpha"; |
|||
* case BETA: return "beta"; |
|||
* case GAMMA: return "gamma"; |
|||
* case DELTA: return "delta"; |
|||
* case EPSILON: return "epsilon"; |
|||
* default: return "**INVALID**"; |
|||
* } |
|||
* } |
|||
* |
|||
* // Use inline if compiler knows answer. Otherwise call function
|
|||
* // to avoid copies of the same code everywhere.
|
|||
* #define greek_name(g) \ |
|||
* (IS_COMPILE_CONSTANT(greek) ? _greek_name(g) : greek_name(g)) |
|||
*/ |
|||
#define IS_COMPILE_CONSTANT(expr) __builtin_constant_p(expr) |
|||
#else |
|||
/* If we don't know, assume it's not. */ |
|||
#define IS_COMPILE_CONSTANT(expr) 0 |
|||
#endif |
|||
#endif |
|||
|
|||
#ifndef WARN_UNUSED_RESULT |
|||
#if HAVE_WARN_UNUSED_RESULT |
|||
/**
|
|||
* WARN_UNUSED_RESULT - warn if a function return value is unused. |
|||
* |
|||
* Used to mark a function where it is extremely unlikely that the caller |
|||
* can ignore the result, eg realloc(). |
|||
* |
|||
* Example: |
|||
* // buf param may be freed by this; need return value!
|
|||
* static char *WARN_UNUSED_RESULT enlarge(char *buf, unsigned *size) |
|||
* { |
|||
* return realloc(buf, (*size) *= 2); |
|||
* } |
|||
*/ |
|||
#define WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) |
|||
#else |
|||
#define WARN_UNUSED_RESULT |
|||
#endif |
|||
#endif |
|||
|
|||
|
|||
#if HAVE_ATTRIBUTE_DEPRECATED |
|||
/**
|
|||
* WARN_DEPRECATED - warn that a function/type/variable is deprecated when used. |
|||
* |
|||
* Used to mark a function, type or variable should not be used. |
|||
* |
|||
* Example: |
|||
* WARN_DEPRECATED char *oldfunc(char *buf); |
|||
*/ |
|||
#define WARN_DEPRECATED __attribute__((__deprecated__)) |
|||
#else |
|||
#define WARN_DEPRECATED |
|||
#endif |
|||
|
|||
|
|||
#if HAVE_ATTRIBUTE_NONNULL |
|||
/**
|
|||
* NO_NULL_ARGS - specify that no arguments to this function can be NULL. |
|||
* |
|||
* The compiler will warn if any pointer args are NULL. |
|||
* |
|||
* Example: |
|||
* NO_NULL_ARGS char *my_copy(char *buf); |
|||
*/ |
|||
#define NO_NULL_ARGS __attribute__((__nonnull__)) |
|||
|
|||
/**
|
|||
* NON_NULL_ARGS - specify that some arguments to this function can't be NULL. |
|||
* @...: 1-based argument numbers for which args can't be NULL. |
|||
* |
|||
* The compiler will warn if any of the specified pointer args are NULL. |
|||
* |
|||
* Example: |
|||
* char *my_copy2(char *buf, char *maybenull) NON_NULL_ARGS(1); |
|||
*/ |
|||
#define NON_NULL_ARGS(...) __attribute__((__nonnull__(__VA_ARGS__))) |
|||
#else |
|||
#define NO_NULL_ARGS |
|||
#define NON_NULL_ARGS(...) |
|||
#endif |
|||
|
|||
#if HAVE_ATTRIBUTE_RETURNS_NONNULL |
|||
/**
|
|||
* RETURNS_NONNULL - specify that this function cannot return NULL. |
|||
* |
|||
* Mainly an optimization opportunity, but can also suppress warnings. |
|||
* |
|||
* Example: |
|||
* RETURNS_NONNULL char *my_copy(char *buf); |
|||
*/ |
|||
#define RETURNS_NONNULL __attribute__((__returns_nonnull__)) |
|||
#else |
|||
#define RETURNS_NONNULL |
|||
#endif |
|||
|
|||
#if HAVE_ATTRIBUTE_SENTINEL |
|||
/**
|
|||
* LAST_ARG_NULL - specify the last argument of a variadic function must be NULL. |
|||
* |
|||
* The compiler will warn if the last argument isn't NULL. |
|||
* |
|||
* Example: |
|||
* char *join_string(char *buf, ...) LAST_ARG_NULL; |
|||
*/ |
|||
#define LAST_ARG_NULL __attribute__((__sentinel__)) |
|||
#else |
|||
#define LAST_ARG_NULL |
|||
#endif |
|||
|
|||
#if HAVE_BUILTIN_CPU_SUPPORTS |
|||
/**
|
|||
* cpu_supports - test if current CPU supports the named feature. |
|||
* |
|||
* This takes a literal string, and currently only works on glibc platforms. |
|||
* |
|||
* Example: |
|||
* if (cpu_supports("mmx")) |
|||
* printf("MMX support engaged!\n"); |
|||
*/ |
|||
#define cpu_supports(x) __builtin_cpu_supports(x) |
|||
#else |
|||
#define cpu_supports(x) 0 |
|||
#endif /* HAVE_BUILTIN_CPU_SUPPORTS */ |
|||
|
|||
#endif /* CCAN_COMPILER_H */ |
@ -0,0 +1,18 @@ |
|||
/* Generated by CCAN configurator */ |
|||
#ifndef CCAN_CONFIG_H |
|||
#define CCAN_CONFIG_H |
|||
#ifndef _GNU_SOURCE |
|||
#define _GNU_SOURCE /* Always use GNU extensions. */ |
|||
#endif |
|||
#define CCAN_COMPILER "cc" |
|||
#define CCAN_CFLAGS "-g3 -ggdb -Wall -Wundef -Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes -Wold-style-definition" |
|||
#define CCAN_OUTPUT_EXE_CFLAG "-o" |
|||
|
|||
#define HAVE_CCAN 1 |
|||
#define HAVE_UNALIGNED_ACCESS 1 |
|||
#define HAVE_TYPEOF 1 |
|||
#define HAVE_BIG_ENDIAN 0 |
|||
#define HAVE_BYTESWAP_H 0 |
|||
#define HAVE_BSWAP_64 0 |
|||
#define HAVE_LITTLE_ENDIAN 1 |
|||
#endif /* CCAN_CONFIG_H */ |
@ -0,0 +1,145 @@ |
|||
/* CC0 (Public domain) - see LICENSE file for details */ |
|||
#ifndef CCAN_CONTAINER_OF_H |
|||
#define CCAN_CONTAINER_OF_H |
|||
#include <stddef.h> |
|||
|
|||
#include "config.h" |
|||
#include "check_type.h" |
|||
|
|||
/**
|
|||
* container_of - get pointer to enclosing structure |
|||
* @member_ptr: pointer to the structure member |
|||
* @containing_type: the type this member is within |
|||
* @member: the name of this member within the structure. |
|||
* |
|||
* Given a pointer to a member of a structure, this macro does pointer |
|||
* subtraction to return the pointer to the enclosing type. |
|||
* |
|||
* Example: |
|||
* struct foo { |
|||
* int fielda, fieldb; |
|||
* // ...
|
|||
* }; |
|||
* struct info { |
|||
* int some_other_field; |
|||
* struct foo my_foo; |
|||
* }; |
|||
* |
|||
* static struct info *foo_to_info(struct foo *foo) |
|||
* { |
|||
* return container_of(foo, struct info, my_foo); |
|||
* } |
|||
*/ |
|||
#define container_of(member_ptr, containing_type, member) \ |
|||
((containing_type *) \ |
|||
((char *)(member_ptr) \ |
|||
- container_off(containing_type, member)) \ |
|||
+ check_types_match(*(member_ptr), ((containing_type *)0)->member)) |
|||
|
|||
|
|||
/**
|
|||
* container_of_or_null - get pointer to enclosing structure, or NULL |
|||
* @member_ptr: pointer to the structure member |
|||
* @containing_type: the type this member is within |
|||
* @member: the name of this member within the structure. |
|||
* |
|||
* Given a pointer to a member of a structure, this macro does pointer |
|||
* subtraction to return the pointer to the enclosing type, unless it |
|||
* is given NULL, in which case it also returns NULL. |
|||
* |
|||
* Example: |
|||
* struct foo { |
|||
* int fielda, fieldb; |
|||
* // ...
|
|||
* }; |
|||
* struct info { |
|||
* int some_other_field; |
|||
* struct foo my_foo; |
|||
* }; |
|||
* |
|||
* static struct info *foo_to_info_allowing_null(struct foo *foo) |
|||
* { |
|||
* return container_of_or_null(foo, struct info, my_foo); |
|||
* } |
|||
*/ |
|||
static inline char *container_of_or_null_(void *member_ptr, size_t offset) |
|||
{ |
|||
return member_ptr ? (char *)member_ptr - offset : NULL; |
|||
} |
|||
#define container_of_or_null(member_ptr, containing_type, member) \ |
|||
((containing_type *) \ |
|||
container_of_or_null_(member_ptr, \ |
|||
container_off(containing_type, member)) \ |
|||
+ check_types_match(*(member_ptr), ((containing_type *)0)->member)) |
|||
|
|||
/**
|
|||
* container_off - get offset to enclosing structure |
|||
* @containing_type: the type this member is within |
|||
* @member: the name of this member within the structure. |
|||
* |
|||
* Given a pointer to a member of a structure, this macro does |
|||
* typechecking and figures out the offset to the enclosing type. |
|||
* |
|||
* Example: |
|||
* struct foo { |
|||
* int fielda, fieldb; |
|||
* // ...
|
|||
* }; |
|||
* struct info { |
|||
* int some_other_field; |
|||
* struct foo my_foo; |
|||
* }; |
|||
* |
|||
* static struct info *foo_to_info(struct foo *foo) |
|||
* { |
|||
* size_t off = container_off(struct info, my_foo); |
|||
* return (void *)((char *)foo - off); |
|||
* } |
|||
*/ |
|||
#define container_off(containing_type, member) \ |
|||
offsetof(containing_type, member) |
|||
|
|||
/**
|
|||
* container_of_var - get pointer to enclosing structure using a variable |
|||
* @member_ptr: pointer to the structure member |
|||
* @container_var: a pointer of same type as this member's container |
|||
* @member: the name of this member within the structure. |
|||
* |
|||
* Given a pointer to a member of a structure, this macro does pointer |
|||
* subtraction to return the pointer to the enclosing type. |
|||
* |
|||
* Example: |
|||
* static struct info *foo_to_i(struct foo *foo) |
|||
* { |
|||
* struct info *i = container_of_var(foo, i, my_foo); |
|||
* return i; |
|||
* } |
|||
*/ |
|||
#if HAVE_TYPEOF |
|||
#define container_of_var(member_ptr, container_var, member) \ |
|||
container_of(member_ptr, typeof(*container_var), member) |
|||
#else |
|||
#define container_of_var(member_ptr, container_var, member) \ |
|||
((void *)((char *)(member_ptr) - \ |
|||
container_off_var(container_var, member))) |
|||
#endif |
|||
|
|||
/**
|
|||
* container_off_var - get offset of a field in enclosing structure |
|||
* @container_var: a pointer to a container structure |
|||
* @member: the name of a member within the structure. |
|||
* |
|||
* Given (any) pointer to a structure and a its member name, this |
|||
* macro does pointer subtraction to return offset of member in a |
|||
* structure memory layout. |
|||
* |
|||
*/ |
|||
#if HAVE_TYPEOF |
|||
#define container_off_var(var, member) \ |
|||
container_off(typeof(*var), member) |
|||
#else |
|||
#define container_off_var(var, member) \ |
|||
((const char *)&(var)->member - (const char *)(var)) |
|||
#endif |
|||
|
|||
#endif /* CCAN_CONTAINER_OF_H */ |
@ -0,0 +1,191 @@ |
|||
/* MIT (BSD) license - see LICENSE file for details */ |
|||
#ifndef CCAN_CPPMAGIC_H |
|||
#define CCAN_CPPMAGIC_H |
|||
|
|||
/**
|
|||
* CPPMAGIC_NOTHING - expands to nothing |
|||
*/ |
|||
#define CPPMAGIC_NOTHING() |
|||
|
|||
/**
|
|||
* CPPMAGIC_STRINGIFY - convert arguments to a string literal |
|||
*/ |
|||
#define _CPPMAGIC_STRINGIFY(...) #__VA_ARGS__ |
|||
#define CPPMAGIC_STRINGIFY(...) _CPPMAGIC_STRINGIFY(__VA_ARGS__) |
|||
|
|||
/**
|
|||
* CPPMAGIC_GLUE2 - glue arguments together |
|||
* |
|||
* CPPMAGIC_GLUE2(@a_, @b_) |
|||
* expands to the expansion of @a_ followed immediately |
|||
* (combining tokens) by the expansion of @b_ |
|||
*/ |
|||
#define _CPPMAGIC_GLUE2(a_, b_) a_##b_ |
|||
#define CPPMAGIC_GLUE2(a_, b_) _CPPMAGIC_GLUE2(a_, b_) |
|||
|
|||
/**
|
|||
* CPPMAGIC_1ST - return 1st argument |
|||
* |
|||
* CPPMAGIC_1ST(@a_, ...) |
|||
* expands to the expansion of @a_ |
|||
*/ |
|||
#define CPPMAGIC_1ST(a_, ...) a_ |
|||
|
|||
/**
|
|||
* CPPMAGIC_2ND - return 2nd argument |
|||
* |
|||
* CPPMAGIC_2ST(@a_, @b_, ...) |
|||
* expands to the expansion of @b_ |
|||
*/ |
|||
#define CPPMAGIC_2ND(a_, b_, ...) b_ |
|||
|
|||
/**
|
|||
* CPPMAGIC_ISZERO - is argument '0' |
|||
* |
|||
* CPPMAGIC_ISZERO(@a) |
|||
* expands to '1' if @a is '0', otherwise expands to '0'. |
|||
*/ |
|||
#define _CPPMAGIC_ISPROBE(...) CPPMAGIC_2ND(__VA_ARGS__, 0) |
|||
#define _CPPMAGIC_PROBE() $, 1 |
|||
#define _CPPMAGIC_ISZERO_0 _CPPMAGIC_PROBE() |
|||
#define CPPMAGIC_ISZERO(a_) \ |
|||
_CPPMAGIC_ISPROBE(CPPMAGIC_GLUE2(_CPPMAGIC_ISZERO_, a_)) |
|||
|
|||
/**
|
|||
* CPPMAGIC_NONZERO - is argument not '0' |
|||
* |
|||
* CPPMAGIC_NONZERO(@a) |
|||
* expands to '0' if @a is '0', otherwise expands to '1'. |
|||
*/ |
|||
#define CPPMAGIC_NONZERO(a_) CPPMAGIC_ISZERO(CPPMAGIC_ISZERO(a_)) |
|||
|
|||
/**
|
|||
* CPPMAGIC_NONEMPTY - does the macro have any arguments? |
|||
* |
|||
* CPPMAGIC_NONEMPTY() |
|||
* expands to '0' |
|||
* CPPMAGIC_NONEMPTY(@a) |
|||
* CPPMAGIC_NONEMPTY(@a, ...) |
|||
* expand to '1' |
|||
*/ |
|||
#define _CPPMAGIC_EOA() 0 |
|||
#define CPPMAGIC_NONEMPTY(...) \ |
|||
CPPMAGIC_NONZERO(CPPMAGIC_1ST(_CPPMAGIC_EOA __VA_ARGS__)()) |
|||
|
|||
/**
|
|||
* CPPMAGIC_ISEMPTY - does the macro have no arguments? |
|||
* |
|||
* CPPMAGIC_ISEMPTY() |
|||
* expands to '1' |
|||
* CPPMAGIC_ISEMPTY(@a) |
|||
* CPPMAGIC_ISEMPTY(@a, ...) |
|||
* expand to '0' |
|||
*/ |
|||
#define CPPMAGIC_ISEMPTY(...) \ |
|||
CPPMAGIC_ISZERO(CPPMAGIC_NONEMPTY(__VA_ARGS__)) |
|||
|
|||
/*
|
|||
* CPPMAGIC_IFELSE - preprocessor conditional |
|||
* |
|||
* CPPMAGIC_IFELSE(@cond)(@if)(@else) |
|||
* expands to @else if @cond is '0', otherwise expands to @if |
|||
*/ |
|||
#define _CPPMAGIC_IF_0(...) _CPPMAGIC_IF_0_ELSE |
|||
#define _CPPMAGIC_IF_1(...) __VA_ARGS__ _CPPMAGIC_IF_1_ELSE |
|||
#define _CPPMAGIC_IF_0_ELSE(...) __VA_ARGS__ |
|||
#define _CPPMAGIC_IF_1_ELSE(...) |
|||
#define _CPPMAGIC_IFELSE(cond_) CPPMAGIC_GLUE2(_CPPMAGIC_IF_, cond_) |
|||
#define CPPMAGIC_IFELSE(cond_) \ |
|||
_CPPMAGIC_IFELSE(CPPMAGIC_NONZERO(cond_)) |
|||
|
|||
/**
|
|||
* CPPMAGIC_EVAL - force multiple expansion passes |
|||
* |
|||
* Forces macros in the arguments to be expanded repeatedly (up to |
|||
* 1024 times) even when CPP would usually stop expanding. |
|||
*/ |
|||
#define CPPMAGIC_EVAL1(...) __VA_ARGS__ |
|||
#define CPPMAGIC_EVAL2(...) \ |
|||
CPPMAGIC_EVAL1(CPPMAGIC_EVAL1(__VA_ARGS__)) |
|||
#define CPPMAGIC_EVAL4(...) \ |
|||
CPPMAGIC_EVAL2(CPPMAGIC_EVAL2(__VA_ARGS__)) |
|||
#define CPPMAGIC_EVAL8(...) \ |
|||
CPPMAGIC_EVAL4(CPPMAGIC_EVAL4(__VA_ARGS__)) |
|||
#define CPPMAGIC_EVAL16(...) \ |
|||
CPPMAGIC_EVAL8(CPPMAGIC_EVAL8(__VA_ARGS__)) |
|||
#define CPPMAGIC_EVAL32(...) \ |
|||
CPPMAGIC_EVAL16(CPPMAGIC_EVAL16(__VA_ARGS__)) |
|||
#define CPPMAGIC_EVAL64(...) \ |
|||
CPPMAGIC_EVAL32(CPPMAGIC_EVAL32(__VA_ARGS__)) |
|||
#define CPPMAGIC_EVAL128(...) \ |
|||
CPPMAGIC_EVAL64(CPPMAGIC_EVAL64(__VA_ARGS__)) |
|||
#define CPPMAGIC_EVAL256(...) \ |
|||
CPPMAGIC_EVAL128(CPPMAGIC_EVAL128(__VA_ARGS__)) |
|||
#define CPPMAGIC_EVAL512(...) \ |
|||
CPPMAGIC_EVAL256(CPPMAGIC_EVAL256(__VA_ARGS__)) |
|||
#define CPPMAGIC_EVAL1024(...) \ |
|||
CPPMAGIC_EVAL512(CPPMAGIC_EVAL512(__VA_ARGS__)) |
|||
#define CPPMAGIC_EVAL(...) CPPMAGIC_EVAL1024(__VA_ARGS__) |
|||
|
|||
/**
|
|||
* CPPMAGIC_DEFER1, CPPMAGIC_DEFER2 - defer expansion |
|||
*/ |
|||
#define CPPMAGIC_DEFER1(a_) a_ CPPMAGIC_NOTHING() |
|||
#define CPPMAGIC_DEFER2(a_) a_ CPPMAGIC_NOTHING CPPMAGIC_NOTHING()() |
|||
|
|||
/**
|
|||
* CPPMAGIC_MAP - iterate another macro across arguments |
|||
* @m: name of a one argument macro |
|||
* |
|||
* CPPMAGIC_MAP(@m, @a1, @a2, ... @an) |
|||
* expands to the expansion of @m(@a1) , @m(@a2) , ... , @m(@an) |
|||
*/ |
|||
#define _CPPMAGIC_MAP_() _CPPMAGIC_MAP |
|||
#define _CPPMAGIC_MAP(m_, a_, ...) \ |
|||
m_(a_) \ |
|||
CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \ |
|||
(, CPPMAGIC_DEFER2(_CPPMAGIC_MAP_)()(m_, __VA_ARGS__)) \ |
|||
() |
|||
#define CPPMAGIC_MAP(m_, ...) \ |
|||
CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \ |
|||
(CPPMAGIC_EVAL(_CPPMAGIC_MAP(m_, __VA_ARGS__))) \ |
|||
() |
|||
|
|||
/**
|
|||
* CPPMAGIC_2MAP - iterate another macro across pairs of arguments |
|||
* @m: name of a two argument macro |
|||
* |
|||
* CPPMAGIC_2MAP(@m, @a1, @b1, @a2, @b2, ..., @an, @bn) |
|||
* expands to the expansion of |
|||
* @m(@a1, @b1) , @m(@a2, @b2) , ... , @m(@an, @bn) |
|||
*/ |
|||
#define _CPPMAGIC_2MAP_() _CPPMAGIC_2MAP |
|||
#define _CPPMAGIC_2MAP(m_, a_, b_, ...) \ |
|||
m_(a_, b_) \ |
|||
CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \ |
|||
(, CPPMAGIC_DEFER2(_CPPMAGIC_2MAP_)()(m_, __VA_ARGS__)) \ |
|||
() |
|||
#define CPPMAGIC_2MAP(m_, ...) \ |
|||
CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \ |
|||
(CPPMAGIC_EVAL(_CPPMAGIC_2MAP(m_, __VA_ARGS__))) \ |
|||
() |
|||
|
|||
/**
|
|||
* CPPMAGIC_JOIN - separate arguments with given delimiter |
|||
* @d: delimiter |
|||
* |
|||
* CPPMAGIC_JOIN(@d, @a1, @a2, ..., @an) |
|||
* expands to the expansion of @a1 @d @a2 @d ... @d @an |
|||
*/ |
|||
#define _CPPMAGIC_JOIN_() _CPPMAGIC_JOIN |
|||
#define _CPPMAGIC_JOIN(d_, a_, ...) \ |
|||
a_ \ |
|||
CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \ |
|||
(d_ CPPMAGIC_DEFER2(_CPPMAGIC_JOIN_)()(d_, __VA_ARGS__)) \ |
|||
() |
|||
#define CPPMAGIC_JOIN(d_, ...) \ |
|||
CPPMAGIC_IFELSE(CPPMAGIC_NONEMPTY(__VA_ARGS__)) \ |
|||
(CPPMAGIC_EVAL(_CPPMAGIC_JOIN(d_, __VA_ARGS__))) \ |
|||
() |
|||
|
|||
#endif /* CCAN_CPPMAGIC_H */ |
@ -0,0 +1,363 @@ |
|||
/* CC0 (Public domain) - see LICENSE file for details */ |
|||
#ifndef CCAN_ENDIAN_H |
|||
#define CCAN_ENDIAN_H |
|||
#include <stdint.h> |
|||
#include "config.h" |
|||
|
|||
/**
|
|||
* BSWAP_16 - reverse bytes in a constant uint16_t value. |
|||
* @val: constant value whose bytes to swap. |
|||
* |
|||
* Designed to be usable in constant-requiring initializers. |
|||
* |
|||
* Example: |
|||
* struct mystruct { |
|||
* char buf[BSWAP_16(0x1234)]; |
|||
* }; |
|||
*/ |
|||
#define BSWAP_16(val) \ |
|||
((((uint16_t)(val) & 0x00ff) << 8) \ |
|||
| (((uint16_t)(val) & 0xff00) >> 8)) |
|||
|
|||
/**
|
|||
* BSWAP_32 - reverse bytes in a constant uint32_t value. |
|||
* @val: constant value whose bytes to swap. |
|||
* |
|||
* Designed to be usable in constant-requiring initializers. |
|||
* |
|||
* Example: |
|||
* struct mystruct { |
|||
* char buf[BSWAP_32(0xff000000)]; |
|||
* }; |
|||
*/ |
|||
#define BSWAP_32(val) \ |
|||
((((uint32_t)(val) & 0x000000ff) << 24) \ |
|||
| (((uint32_t)(val) & 0x0000ff00) << 8) \ |
|||
| (((uint32_t)(val) & 0x00ff0000) >> 8) \ |
|||
| (((uint32_t)(val) & 0xff000000) >> 24)) |
|||
|
|||
/**
|
|||
* BSWAP_64 - reverse bytes in a constant uint64_t value. |
|||
* @val: constantvalue whose bytes to swap. |
|||
* |
|||
* Designed to be usable in constant-requiring initializers. |
|||
* |
|||
* Example: |
|||
* struct mystruct { |
|||
* char buf[BSWAP_64(0xff00000000000000ULL)]; |
|||
* }; |
|||
*/ |
|||
#define BSWAP_64(val) \ |
|||
((((uint64_t)(val) & 0x00000000000000ffULL) << 56) \ |
|||
| (((uint64_t)(val) & 0x000000000000ff00ULL) << 40) \ |
|||
| (((uint64_t)(val) & 0x0000000000ff0000ULL) << 24) \ |
|||
| (((uint64_t)(val) & 0x00000000ff000000ULL) << 8) \ |
|||
| (((uint64_t)(val) & 0x000000ff00000000ULL) >> 8) \ |
|||
| (((uint64_t)(val) & 0x0000ff0000000000ULL) >> 24) \ |
|||
| (((uint64_t)(val) & 0x00ff000000000000ULL) >> 40) \ |
|||
| (((uint64_t)(val) & 0xff00000000000000ULL) >> 56)) |
|||
|
|||
#if HAVE_BYTESWAP_H |
|||
#include <byteswap.h> |
|||
#else |
|||
/**
|
|||
* bswap_16 - reverse bytes in a uint16_t value. |
|||
* @val: value whose bytes to swap. |
|||
* |
|||
* Example: |
|||
* // Output contains "1024 is 4 as two bytes reversed"
|
|||
* printf("1024 is %u as two bytes reversed\n", bswap_16(1024)); |
|||
*/ |
|||
static inline uint16_t bswap_16(uint16_t val) |
|||
{ |
|||
return BSWAP_16(val); |
|||
} |
|||
|
|||
/**
|
|||
* bswap_32 - reverse bytes in a uint32_t value. |
|||
* @val: value whose bytes to swap. |
|||
* |
|||
* Example: |
|||
* // Output contains "1024 is 262144 as four bytes reversed"
|
|||
* printf("1024 is %u as four bytes reversed\n", bswap_32(1024)); |
|||
*/ |
|||
static inline uint32_t bswap_32(uint32_t val) |
|||
{ |
|||
return BSWAP_32(val); |
|||
} |
|||
#endif /* !HAVE_BYTESWAP_H */ |
|||
|
|||
#if !HAVE_BSWAP_64 |
|||
/**
|
|||
* bswap_64 - reverse bytes in a uint64_t value. |
|||
* @val: value whose bytes to swap. |
|||
* |
|||
* Example: |
|||
* // Output contains "1024 is 1125899906842624 as eight bytes reversed"
|
|||
* printf("1024 is %llu as eight bytes reversed\n", |
|||
* (unsigned long long)bswap_64(1024)); |
|||
*/ |
|||
static inline uint64_t bswap_64(uint64_t val) |
|||
{ |
|||
return BSWAP_64(val); |
|||
} |
|||
#endif |
|||
|
|||
/* Needed for Glibc like endiness check */ |
|||
#define __LITTLE_ENDIAN 1234 |
|||
#define __BIG_ENDIAN 4321 |
|||
|
|||
/* Sanity check the defines. We don't handle weird endianness. */ |
|||
#if !HAVE_LITTLE_ENDIAN && !HAVE_BIG_ENDIAN |
|||
#error "Unknown endian" |
|||
#elif HAVE_LITTLE_ENDIAN && HAVE_BIG_ENDIAN |
|||
#error "Can't compile for both big and little endian." |
|||
#elif HAVE_LITTLE_ENDIAN |
|||
#ifndef __BYTE_ORDER |
|||
#define __BYTE_ORDER __LITTLE_ENDIAN |
|||
#elif __BYTE_ORDER != __LITTLE_ENDIAN |
|||
#error "__BYTE_ORDER already defined, but not equal to __LITTLE_ENDIAN" |
|||
#endif |
|||
#elif HAVE_BIG_ENDIAN |
|||
#ifndef __BYTE_ORDER |
|||
#define __BYTE_ORDER __BIG_ENDIAN |
|||
#elif __BYTE_ORDER != __BIG_ENDIAN |
|||
#error "__BYTE_ORDER already defined, but not equal to __BIG_ENDIAN" |
|||
#endif |
|||
#endif |
|||
|
|||
|
|||
#ifdef __CHECKER__ |
|||
/* sparse needs forcing to remove bitwise attribute from ccan/short_types */ |
|||
#define ENDIAN_CAST __attribute__((force)) |
|||
#define ENDIAN_TYPE __attribute__((bitwise)) |
|||
#else |
|||
#define ENDIAN_CAST |
|||
#define ENDIAN_TYPE |
|||
#endif |
|||
|
|||
typedef uint64_t ENDIAN_TYPE leint64_t; |
|||
typedef uint64_t ENDIAN_TYPE beint64_t; |
|||
typedef uint32_t ENDIAN_TYPE leint32_t; |
|||
typedef uint32_t ENDIAN_TYPE beint32_t; |
|||
typedef uint16_t ENDIAN_TYPE leint16_t; |
|||
typedef uint16_t ENDIAN_TYPE beint16_t; |
|||
|
|||
#if HAVE_LITTLE_ENDIAN |
|||
/**
|
|||
* CPU_TO_LE64 - convert a constant uint64_t value to little-endian |
|||
* @native: constant to convert |
|||
*/ |
|||
#define CPU_TO_LE64(native) ((ENDIAN_CAST leint64_t)(native)) |
|||
|
|||
/**
|
|||
* CPU_TO_LE32 - convert a constant uint32_t value to little-endian |
|||
* @native: constant to convert |
|||
*/ |
|||
#define CPU_TO_LE32(native) ((ENDIAN_CAST leint32_t)(native)) |
|||
|
|||
/**
|
|||
* CPU_TO_LE16 - convert a constant uint16_t value to little-endian |
|||
* @native: constant to convert |
|||
*/ |
|||
#define CPU_TO_LE16(native) ((ENDIAN_CAST leint16_t)(native)) |
|||
|
|||
/**
|
|||
* LE64_TO_CPU - convert a little-endian uint64_t constant |
|||
* @le_val: little-endian constant to convert |
|||
*/ |
|||
#define LE64_TO_CPU(le_val) ((ENDIAN_CAST uint64_t)(le_val)) |
|||
|
|||
/**
|
|||
* LE32_TO_CPU - convert a little-endian uint32_t constant |
|||
* @le_val: little-endian constant to convert |
|||
*/ |
|||
#define LE32_TO_CPU(le_val) ((ENDIAN_CAST uint32_t)(le_val)) |
|||
|
|||
/**
|
|||
* LE16_TO_CPU - convert a little-endian uint16_t constant |
|||
* @le_val: little-endian constant to convert |
|||
*/ |
|||
#define LE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val)) |
|||
|
|||
#else /* ... HAVE_BIG_ENDIAN */ |
|||
#define CPU_TO_LE64(native) ((ENDIAN_CAST leint64_t)BSWAP_64(native)) |
|||
#define CPU_TO_LE32(native) ((ENDIAN_CAST leint32_t)BSWAP_32(native)) |
|||
#define CPU_TO_LE16(native) ((ENDIAN_CAST leint16_t)BSWAP_16(native)) |
|||
#define LE64_TO_CPU(le_val) BSWAP_64((ENDIAN_CAST uint64_t)le_val) |
|||
#define LE32_TO_CPU(le_val) BSWAP_32((ENDIAN_CAST uint32_t)le_val) |
|||
#define LE16_TO_CPU(le_val) BSWAP_16((ENDIAN_CAST uint16_t)le_val) |
|||
#endif /* HAVE_BIG_ENDIAN */ |
|||
|
|||
#if HAVE_BIG_ENDIAN |
|||
/**
|
|||
* CPU_TO_BE64 - convert a constant uint64_t value to big-endian |
|||
* @native: constant to convert |
|||
*/ |
|||
#define CPU_TO_BE64(native) ((ENDIAN_CAST beint64_t)(native)) |
|||
|
|||
/**
|
|||
* CPU_TO_BE32 - convert a constant uint32_t value to big-endian |
|||
* @native: constant to convert |
|||
*/ |
|||
#define CPU_TO_BE32(native) ((ENDIAN_CAST beint32_t)(native)) |
|||
|
|||
/**
|
|||
* CPU_TO_BE16 - convert a constant uint16_t value to big-endian |
|||
* @native: constant to convert |
|||
*/ |
|||
#define CPU_TO_BE16(native) ((ENDIAN_CAST beint16_t)(native)) |
|||
|
|||
/**
|
|||
* BE64_TO_CPU - convert a big-endian uint64_t constant |
|||
* @le_val: big-endian constant to convert |
|||
*/ |
|||
#define BE64_TO_CPU(le_val) ((ENDIAN_CAST uint64_t)(le_val)) |
|||
|
|||
/**
|
|||
* BE32_TO_CPU - convert a big-endian uint32_t constant |
|||
* @le_val: big-endian constant to convert |
|||
*/ |
|||
#define BE32_TO_CPU(le_val) ((ENDIAN_CAST uint32_t)(le_val)) |
|||
|
|||
/**
|
|||
* BE16_TO_CPU - convert a big-endian uint16_t constant |
|||
* @le_val: big-endian constant to convert |
|||
*/ |
|||
#define BE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val)) |
|||
|
|||
#else /* ... HAVE_LITTLE_ENDIAN */ |
|||
#define CPU_TO_BE64(native) ((ENDIAN_CAST beint64_t)BSWAP_64(native)) |
|||
#define CPU_TO_BE32(native) ((ENDIAN_CAST beint32_t)BSWAP_32(native)) |
|||
#define CPU_TO_BE16(native) ((ENDIAN_CAST beint16_t)BSWAP_16(native)) |
|||
#define BE64_TO_CPU(le_val) BSWAP_64((ENDIAN_CAST uint64_t)le_val) |
|||
#define BE32_TO_CPU(le_val) BSWAP_32((ENDIAN_CAST uint32_t)le_val) |
|||
#define BE16_TO_CPU(le_val) BSWAP_16((ENDIAN_CAST uint16_t)le_val) |
|||
#endif /* HAVE_LITTE_ENDIAN */ |
|||
|
|||
|
|||
/**
|
|||
* cpu_to_le64 - convert a uint64_t value to little-endian |
|||
* @native: value to convert |
|||
*/ |
|||
static inline leint64_t cpu_to_le64(uint64_t native) |
|||
{ |
|||
return CPU_TO_LE64(native); |
|||
} |
|||
|
|||
/**
|
|||
* cpu_to_le32 - convert a uint32_t value to little-endian |
|||
* @native: value to convert |
|||
*/ |
|||
static inline leint32_t cpu_to_le32(uint32_t native) |
|||
{ |
|||
return CPU_TO_LE32(native); |
|||
} |
|||
|
|||
/**
|
|||
* cpu_to_le16 - convert a uint16_t value to little-endian |
|||
* @native: value to convert |
|||
*/ |
|||
static inline leint16_t cpu_to_le16(uint16_t native) |
|||
{ |
|||
return CPU_TO_LE16(native); |
|||
} |
|||
|
|||
/**
|
|||
* le64_to_cpu - convert a little-endian uint64_t value |
|||
* @le_val: little-endian value to convert |
|||
*/ |
|||
static inline uint64_t le64_to_cpu(leint64_t le_val) |
|||
{ |
|||
return LE64_TO_CPU(le_val); |
|||
} |
|||
|
|||
/**
|
|||
* le32_to_cpu - convert a little-endian uint32_t value |
|||
* @le_val: little-endian value to convert |
|||
*/ |
|||
static inline uint32_t le32_to_cpu(leint32_t le_val) |
|||
{ |
|||
return LE32_TO_CPU(le_val); |
|||
} |
|||
|
|||
/**
|
|||
* le16_to_cpu - convert a little-endian uint16_t value |
|||
* @le_val: little-endian value to convert |
|||
*/ |
|||
static inline uint16_t le16_to_cpu(leint16_t le_val) |
|||
{ |
|||
return LE16_TO_CPU(le_val); |
|||
} |
|||
|
|||
/**
|
|||
* cpu_to_be64 - convert a uint64_t value to big endian. |
|||
* @native: value to convert |
|||
*/ |
|||
static inline beint64_t cpu_to_be64(uint64_t native) |
|||
{ |
|||
return CPU_TO_BE64(native); |
|||
} |
|||
|
|||
/**
|
|||
* cpu_to_be32 - convert a uint32_t value to big endian. |
|||
* @native: value to convert |
|||
*/ |
|||
static inline beint32_t cpu_to_be32(uint32_t native) |
|||
{ |
|||
return CPU_TO_BE32(native); |
|||
} |
|||
|
|||
/**
|
|||
* cpu_to_be16 - convert a uint16_t value to big endian. |
|||
* @native: value to convert |
|||
*/ |
|||
static inline beint16_t cpu_to_be16(uint16_t native) |
|||
{ |
|||
return CPU_TO_BE16(native); |
|||
} |
|||
|
|||
/**
|
|||
* be64_to_cpu - convert a big-endian uint64_t value |
|||
* @be_val: big-endian value to convert |
|||
*/ |
|||
static inline uint64_t be64_to_cpu(beint64_t be_val) |
|||
{ |
|||
return BE64_TO_CPU(be_val); |
|||
} |
|||
|
|||
/**
|
|||
* be32_to_cpu - convert a big-endian uint32_t value |
|||
* @be_val: big-endian value to convert |
|||
*/ |
|||
static inline uint32_t be32_to_cpu(beint32_t be_val) |
|||
{ |
|||
return BE32_TO_CPU(be_val); |
|||
} |
|||
|
|||
/**
|
|||
* be16_to_cpu - convert a big-endian uint16_t value |
|||
* @be_val: big-endian value to convert |
|||
*/ |
|||
static inline uint16_t be16_to_cpu(beint16_t be_val) |
|||
{ |
|||
return BE16_TO_CPU(be_val); |
|||
} |
|||
|
|||
/* Whichever they include first, they get these definitions. */ |
|||
#ifdef CCAN_SHORT_TYPES_H |
|||
/**
|
|||
* be64/be32/be16 - 64/32/16 bit big-endian representation. |
|||
*/ |
|||
typedef beint64_t be64; |
|||
typedef beint32_t be32; |
|||
typedef beint16_t be16; |
|||
|
|||
/**
|
|||
* le64/le32/le16 - 64/32/16 bit little-endian representation. |
|||
*/ |
|||
typedef leint64_t le64; |
|||
typedef leint32_t le32; |
|||
typedef leint16_t le16; |
|||
#endif |
|||
#endif /* CCAN_ENDIAN_H */ |
@ -0,0 +1,48 @@ |
|||
#include "config.h" |
|||
#include "endian.h" |
|||
#include "hash_u5.h" |
|||
#include <string.h> |
|||
|
|||
void hash_u5_init(struct hash_u5 *hu5, const char *hrp) |
|||
{ |
|||
hu5->buf = 0; |
|||
hu5->num_bits = 0; |
|||
sha256_init(&hu5->hash); |
|||
sha256_update(&hu5->hash, hrp, strlen(hrp)); |
|||
} |
|||
|
|||
void hash_u5(struct hash_u5 *hu5, const u8 *u5, size_t len) |
|||
{ |
|||
size_t bits = len * 5; |
|||
|
|||
while (bits) { |
|||
size_t n = 5; |
|||
|
|||
if (bits < n) |
|||
n = bits; |
|||
|
|||
hu5->buf <<= n; |
|||
hu5->buf |= (*u5 >> (5-n)); |
|||
bits -= n; |
|||
hu5->num_bits += n; |
|||
|
|||
if (n == 5) |
|||
u5++; |
|||
|
|||
if (hu5->num_bits >= 32) { |
|||
be32 be32 = cpu_to_be32(hu5->buf >> (hu5->num_bits-32)); |
|||
sha256_update(&hu5->hash, &be32, sizeof(be32)); |
|||
hu5->num_bits -= 32; |
|||
} |
|||
} |
|||
} |
|||
|
|||
void hash_u5_done(struct hash_u5 *hu5, struct sha256 *res) |
|||
{ |
|||
if (hu5->num_bits) { |
|||
be32 be32 = cpu_to_be32(hu5->buf << (32 - hu5->num_bits)); |
|||
|
|||
sha256_update(&hu5->hash, &be32, (hu5->num_bits + 7) / 8); |
|||
} |
|||
sha256_done(&hu5->hash, res); |
|||
} |
@ -0,0 +1,20 @@ |
|||
/* bech32 (thus bolt11) deal in 5-bit values */ |
|||
#ifndef LIGHTNING_COMMON_HASH_U5_H |
|||
#define LIGHTNING_COMMON_HASH_U5_H |
|||
#include "sha256.h" |
|||
#include "short_types.h" |
|||
|
|||
/* Type to annotate a 5 bit value. */ |
|||
typedef unsigned char u5; |
|||
|
|||
struct hash_u5 { |
|||
u64 buf; |
|||
unsigned int num_bits; |
|||
struct sha256_ctx hash; |
|||
}; |
|||
|
|||
void hash_u5_init(struct hash_u5 *hu5, const char *hrp); |
|||
void hash_u5(struct hash_u5 *hu5, const u5 *u5, size_t len); |
|||
void hash_u5_done(struct hash_u5 *hu5, struct sha256 *res); |
|||
|
|||
#endif /* LIGHTNING_COMMON_HASH_U5_H */ |
@ -0,0 +1,66 @@ |
|||
/* CC0 license (public domain) - see LICENSE file for details */ |
|||
#include "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 i; |
|||
|
|||
if (destsize < hex_str_size(bufsize)) |
|||
return false; |
|||
|
|||
for (i = 0; i < bufsize; i++) { |
|||
unsigned int c = ((const unsigned char *)buf)[i]; |
|||
*(dest++) = hexchar(c >> 4); |
|||
*(dest++) = hexchar(c & 0xF); |
|||
} |
|||
*dest = '\0'; |
|||
|
|||
return true; |
|||
} |
@ -0,0 +1,73 @@ |
|||
/* 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 hexadecimal string |
|||
* @slen: the length of @str |
|||
* @buf: the buffer to write the data into |
|||
* @bufsize: the length of |
|||
* |
|||
* 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 /* CCAN_HEX_H */ |
@ -0,0 +1,111 @@ |
|||
/* CC0 (Public domain) - see LICENSE file for details */ |
|||
#ifndef CCAN_LIKELY_H |
|||
#define CCAN_LIKELY_H |
|||
#include "config.h" |
|||
#include <stdbool.h> |
|||
|
|||
#ifndef CCAN_LIKELY_DEBUG |
|||
#if HAVE_BUILTIN_EXPECT |
|||
/**
|
|||
* likely - indicate that a condition is likely to be true. |
|||
* @cond: the condition |
|||
* |
|||
* This uses a compiler extension where available to indicate a likely |
|||
* code path and optimize appropriately; it's also useful for readers |
|||
* to quickly identify exceptional paths through functions. The |
|||
* threshold for "likely" is usually considered to be between 90 and |
|||
* 99%; marginal cases should not be marked either way. |
|||
* |
|||
* See Also: |
|||
* unlikely(), likely_stats() |
|||
* |
|||
* Example: |
|||
* // Returns false if we overflow.
|
|||
* static inline bool inc_int(unsigned int *val) |
|||
* { |
|||
* (*val)++; |
|||
* if (likely(*val)) |
|||
* return true; |
|||
* return false; |
|||
* } |
|||
*/ |
|||
#define likely(cond) __builtin_expect(!!(cond), 1) |
|||
|
|||
/**
|
|||
* unlikely - indicate that a condition is unlikely to be true. |
|||
* @cond: the condition |
|||
* |
|||
* This uses a compiler extension where available to indicate an unlikely |
|||
* code path and optimize appropriately; see likely() above. |
|||
* |
|||
* See Also: |
|||
* likely(), likely_stats(), COLD (compiler.h) |
|||
* |
|||
* Example: |
|||
* // Prints a warning if we overflow.
|
|||
* static inline void inc_int(unsigned int *val) |
|||
* { |
|||
* (*val)++; |
|||
* if (unlikely(*val == 0)) |
|||
* fprintf(stderr, "Overflow!"); |
|||
* } |
|||
*/ |
|||
#define unlikely(cond) __builtin_expect(!!(cond), 0) |
|||
#else |
|||
#define likely(cond) (!!(cond)) |
|||
#define unlikely(cond) (!!(cond)) |
|||
#endif |
|||
#else /* CCAN_LIKELY_DEBUG versions */ |
|||
#include <ccan/str/str.h> |
|||
|
|||
#define likely(cond) \ |
|||
(_likely_trace(!!(cond), 1, stringify(cond), __FILE__, __LINE__)) |
|||
#define unlikely(cond) \ |
|||
(_likely_trace(!!(cond), 0, stringify(cond), __FILE__, __LINE__)) |
|||
|
|||
long _likely_trace(bool cond, bool expect, |
|||
const char *condstr, |
|||
const char *file, unsigned int line); |
|||
/**
|
|||
* likely_stats - return description of abused likely()/unlikely() |
|||
* @min_hits: minimum number of hits |
|||
* @percent: maximum percentage correct |
|||
* |
|||
* When CCAN_LIKELY_DEBUG is defined, likely() and unlikely() trace their |
|||
* results: this causes a significant slowdown, but allows analysis of |
|||
* whether the branches are labelled correctly. |
|||
* |
|||
* This function returns a malloc'ed description of the least-correct |
|||
* usage of likely() or unlikely(). It ignores places which have been |
|||
* called less than @min_hits times, and those which were predicted |
|||
* correctly more than @percent of the time. It returns NULL when |
|||
* nothing meets those criteria. |
|||
* |
|||
* Note that this call is destructive; the returned offender is |
|||
* removed from the trace so that the next call to likely_stats() will |
|||
* return the next-worst likely()/unlikely() usage. |
|||
* |
|||
* Example: |
|||
* // Print every place hit more than twice which was wrong > 5%.
|
|||
* static void report_stats(void) |
|||
* { |
|||
* #ifdef CCAN_LIKELY_DEBUG |
|||
* const char *bad; |
|||
* |
|||
* while ((bad = likely_stats(2, 95)) != NULL) { |
|||
* printf("Suspicious likely: %s", bad); |
|||
* free(bad); |
|||
* } |
|||
* #endif |
|||
* } |
|||
*/ |
|||
char *likely_stats(unsigned int min_hits, unsigned int percent); |
|||
|
|||
/**
|
|||
* likely_stats_reset - free up memory of likely()/unlikely() branches. |
|||
* |
|||
* This can also plug memory leaks. |
|||
*/ |
|||
void likely_stats_reset(void); |
|||
#endif /* CCAN_LIKELY_DEBUG */ |
|||
#endif /* CCAN_LIKELY_H */ |
@ -0,0 +1,43 @@ |
|||
/* Licensed under BSD-MIT - see LICENSE file for details */ |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include "list.h" |
|||
|
|||
static void *corrupt(const char *abortstr, |
|||
const struct list_node *head, |
|||
const struct list_node *node, |
|||
unsigned int count) |
|||
{ |
|||
if (abortstr) { |
|||
fprintf(stderr, |
|||
"%s: prev corrupt in node %p (%u) of %p\n", |
|||
abortstr, node, count, head); |
|||
abort(); |
|||
} |
|||
return NULL; |
|||
} |
|||
|
|||
struct list_node *list_check_node(const struct list_node *node, |
|||
const char *abortstr) |
|||
{ |
|||
const struct list_node *p, *n; |
|||
int count = 0; |
|||
|
|||
for (p = node, n = node->next; n != node; p = n, n = n->next) { |
|||
count++; |
|||
if (n->prev != p) |
|||
return corrupt(abortstr, node, n, count); |
|||
} |
|||
/* Check prev on head node. */ |
|||
if (node->prev != p) |
|||
return corrupt(abortstr, node, node, 0); |
|||
|
|||
return (struct list_node *)node; |
|||
} |
|||
|
|||
struct list_head *list_check(const struct list_head *h, const char *abortstr) |
|||
{ |
|||
if (!list_check_node(&h->n, abortstr)) |
|||
return NULL; |
|||
return (struct list_head *)h; |
|||
} |
@ -0,0 +1,842 @@ |
|||
/* Licensed under BSD-MIT - see LICENSE file for details */ |
|||
#ifndef CCAN_LIST_H |
|||
#define CCAN_LIST_H |
|||
//#define CCAN_LIST_DEBUG 1
|
|||
#include <stdbool.h> |
|||
#include <assert.h> |
|||
#include "str.h" |
|||
#include "container_of.h" |
|||
#include "check_type.h" |
|||
|
|||
/**
|
|||
* struct list_node - an entry in a doubly-linked list |
|||
* @next: next entry (self if empty) |
|||
* @prev: previous entry (self if empty) |
|||
* |
|||
* This is used as an entry in a linked list. |
|||
* Example: |
|||
* struct child { |
|||
* const char *name; |
|||
* // Linked list of all us children.
|
|||
* struct list_node list; |
|||
* }; |
|||
*/ |
|||
struct list_node |
|||
{ |
|||
struct list_node *next, *prev; |
|||
}; |
|||
|
|||
/**
|
|||
* struct list_head - the head of a doubly-linked list |
|||
* @h: the list_head (containing next and prev pointers) |
|||
* |
|||
* This is used as the head of a linked list. |
|||
* Example: |
|||
* struct parent { |
|||
* const char *name; |
|||
* struct list_head children; |
|||
* unsigned int num_children; |
|||
* }; |
|||
*/ |
|||
struct list_head |
|||
{ |
|||
struct list_node n; |
|||
}; |
|||
|
|||
/**
|
|||
* list_check - check head of a list for consistency |
|||
* @h: the list_head |
|||
* @abortstr: the location to print on aborting, or NULL. |
|||
* |
|||
* Because list_nodes have redundant information, consistency checking between |
|||
* the back and forward links can be done. This is useful as a debugging check. |
|||
* If @abortstr is non-NULL, that will be printed in a diagnostic if the list |
|||
* is inconsistent, and the function will abort. |
|||
* |
|||
* Returns the list head if the list is consistent, NULL if not (it |
|||
* can never return NULL if @abortstr is set). |
|||
* |
|||
* See also: list_check_node() |
|||
* |
|||
* Example: |
|||
* static void dump_parent(struct parent *p) |
|||
* { |
|||
* struct child *c; |
|||
* |
|||
* printf("%s (%u children):\n", p->name, p->num_children); |
|||
* list_check(&p->children, "bad child list"); |
|||
* list_for_each(&p->children, c, list) |
|||
* printf(" -> %s\n", c->name); |
|||
* } |
|||
*/ |
|||
struct list_head *list_check(const struct list_head *h, const char *abortstr); |
|||
|
|||
/**
|
|||
* list_check_node - check node of a list for consistency |
|||
* @n: the list_node |
|||
* @abortstr: the location to print on aborting, or NULL. |
|||
* |
|||
* Check consistency of the list node is in (it must be in one). |
|||
* |
|||
* See also: list_check() |
|||
* |
|||
* Example: |
|||
* static void dump_child(const struct child *c) |
|||
* { |
|||
* list_check_node(&c->list, "bad child list"); |
|||
* printf("%s\n", c->name); |
|||
* } |
|||
*/ |
|||
struct list_node *list_check_node(const struct list_node *n, |
|||
const char *abortstr); |
|||
|
|||
#define LIST_LOC __FILE__ ":" stringify(__LINE__) |
|||
#ifdef CCAN_LIST_DEBUG |
|||
#define list_debug(h, loc) list_check((h), loc) |
|||
#define list_debug_node(n, loc) list_check_node((n), loc) |
|||
#else |
|||
#define list_debug(h, loc) ((void)loc, h) |
|||
#define list_debug_node(n, loc) ((void)loc, n) |
|||
#endif |
|||
|
|||
/**
|
|||
* LIST_HEAD_INIT - initializer for an empty list_head |
|||
* @name: the name of the list. |
|||
* |
|||
* Explicit initializer for an empty list. |
|||
* |
|||
* See also: |
|||
* LIST_HEAD, list_head_init() |
|||
* |
|||
* Example: |
|||
* static struct list_head my_list = LIST_HEAD_INIT(my_list); |
|||
*/ |
|||
#define LIST_HEAD_INIT(name) { { &(name).n, &(name).n } } |
|||
|
|||
/**
|
|||
* LIST_HEAD - define and initialize an empty list_head |
|||
* @name: the name of the list. |
|||
* |
|||
* The LIST_HEAD macro defines a list_head and initializes it to an empty |
|||
* list. It can be prepended by "static" to define a static list_head. |
|||
* |
|||
* See also: |
|||
* LIST_HEAD_INIT, list_head_init() |
|||
* |
|||
* Example: |
|||
* static LIST_HEAD(my_global_list); |
|||
*/ |
|||
#define LIST_HEAD(name) \ |
|||
struct list_head name = LIST_HEAD_INIT(name) |
|||
|
|||
/**
|
|||
* list_head_init - initialize a list_head |
|||
* @h: the list_head to set to the empty list |
|||
* |
|||
* Example: |
|||
* ... |
|||
* struct parent *parent = malloc(sizeof(*parent)); |
|||
* |
|||
* list_head_init(&parent->children); |
|||
* parent->num_children = 0; |
|||
*/ |
|||
static inline void list_head_init(struct list_head *h) |
|||
{ |
|||
h->n.next = h->n.prev = &h->n; |
|||
} |
|||
|
|||
/**
|
|||
* list_node_init - initialize a list_node |
|||
* @n: the list_node to link to itself. |
|||
* |
|||
* You don't need to use this normally! But it lets you list_del(@n) |
|||
* safely. |
|||
*/ |
|||
static inline void list_node_init(struct list_node *n) |
|||
{ |
|||
n->next = n->prev = n; |
|||
} |
|||
|
|||
/**
|
|||
* list_add_after - add an entry after an existing node in a linked list |
|||
* @h: the list_head to add the node to (for debugging) |
|||
* @p: the existing list_node to add the node after |
|||
* @n: the new list_node to add to the list. |
|||
* |
|||
* The existing list_node must already be a member of the list. |
|||
* The new list_node does not need to be initialized; it will be overwritten. |
|||
* |
|||
* Example: |
|||
* struct child c1, c2, c3; |
|||
* LIST_HEAD(h); |
|||
* |
|||
* list_add_tail(&h, &c1.list); |
|||
* list_add_tail(&h, &c3.list); |
|||
* list_add_after(&h, &c1.list, &c2.list); |
|||
*/ |
|||
#define list_add_after(h, p, n) list_add_after_(h, p, n, LIST_LOC) |
|||
static inline void list_add_after_(struct list_head *h, |
|||
struct list_node *p, |
|||
struct list_node *n, |
|||
const char *abortstr) |
|||
{ |
|||
n->next = p->next; |
|||
n->prev = p; |
|||
p->next->prev = n; |
|||
p->next = n; |
|||
(void)list_debug(h, abortstr); |
|||
} |
|||
|
|||
/**
|
|||
* list_add - add an entry at the start of a linked list. |
|||
* @h: the list_head to add the node to |
|||
* @n: the list_node to add to the list. |
|||
* |
|||
* The list_node does not need to be initialized; it will be overwritten. |
|||
* Example: |
|||
* struct child *child = malloc(sizeof(*child)); |
|||
* |
|||
* child->name = "marvin"; |
|||
* list_add(&parent->children, &child->list); |
|||
* parent->num_children++; |
|||
*/ |
|||
#define list_add(h, n) list_add_(h, n, LIST_LOC) |
|||
static inline void list_add_(struct list_head *h, |
|||
struct list_node *n, |
|||
const char *abortstr) |
|||
{ |
|||
list_add_after_(h, &h->n, n, abortstr); |
|||
} |
|||
|
|||
/**
|
|||
* list_add_before - add an entry before an existing node in a linked list |
|||
* @h: the list_head to add the node to (for debugging) |
|||
* @p: the existing list_node to add the node before |
|||
* @n: the new list_node to add to the list. |
|||
* |
|||
* The existing list_node must already be a member of the list. |
|||
* The new list_node does not need to be initialized; it will be overwritten. |
|||
* |
|||
* Example: |
|||
* list_head_init(&h); |
|||
* list_add_tail(&h, &c1.list); |
|||
* list_add_tail(&h, &c3.list); |
|||
* list_add_before(&h, &c3.list, &c2.list); |
|||
*/ |
|||
#define list_add_before(h, p, n) list_add_before_(h, p, n, LIST_LOC) |
|||
static inline void list_add_before_(struct list_head *h, |
|||
struct list_node *p, |
|||
struct list_node *n, |
|||
const char *abortstr) |
|||
{ |
|||
n->next = p; |
|||
n->prev = p->prev; |
|||
p->prev->next = n; |
|||
p->prev = n; |
|||
(void)list_debug(h, abortstr); |
|||
} |
|||
|
|||
/**
|
|||
* list_add_tail - add an entry at the end of a linked list. |
|||
* @h: the list_head to add the node to |
|||
* @n: the list_node to add to the list. |
|||
* |
|||
* The list_node does not need to be initialized; it will be overwritten. |
|||
* Example: |
|||
* list_add_tail(&parent->children, &child->list); |
|||
* parent->num_children++; |
|||
*/ |
|||
#define list_add_tail(h, n) list_add_tail_(h, n, LIST_LOC) |
|||
static inline void list_add_tail_(struct list_head *h, |
|||
struct list_node *n, |
|||
const char *abortstr) |
|||
{ |
|||
list_add_before_(h, &h->n, n, abortstr); |
|||
} |
|||
|
|||
/**
|
|||
* list_empty - is a list empty? |
|||
* @h: the list_head |
|||
* |
|||
* If the list is empty, returns true. |
|||
* |
|||
* Example: |
|||
* assert(list_empty(&parent->children) == (parent->num_children == 0)); |
|||
*/ |
|||
#define list_empty(h) list_empty_(h, LIST_LOC) |
|||
static inline bool list_empty_(const struct list_head *h, const char* abortstr) |
|||
{ |
|||
(void)list_debug(h, abortstr); |
|||
return h->n.next == &h->n; |
|||
} |
|||
|
|||
/**
|
|||
* list_empty_nodebug - is a list empty (and don't perform debug checks)? |
|||
* @h: the list_head |
|||
* |
|||
* If the list is empty, returns true. |
|||
* This differs from list_empty() in that if CCAN_LIST_DEBUG is set it |
|||
* will NOT perform debug checks. Only use this function if you REALLY |
|||
* know what you're doing. |
|||
* |
|||
* Example: |
|||
* assert(list_empty_nodebug(&parent->children) == (parent->num_children == 0)); |
|||
*/ |
|||
#ifndef CCAN_LIST_DEBUG |
|||
#define list_empty_nodebug(h) list_empty(h) |
|||
#else |
|||
static inline bool list_empty_nodebug(const struct list_head *h) |
|||
{ |
|||
return h->n.next == &h->n; |
|||
} |
|||
#endif |
|||
|
|||
/**
|
|||
* list_empty_nocheck - is a list empty? |
|||
* @h: the list_head |
|||
* |
|||
* If the list is empty, returns true. This doesn't perform any |
|||
* debug check for list consistency, so it can be called without |
|||
* locks, racing with the list being modified. This is ok for |
|||
* checks where an incorrect result is not an issue (optimized |
|||
* bail out path for example). |
|||
*/ |
|||
static inline bool list_empty_nocheck(const struct list_head *h) |
|||
{ |
|||
return h->n.next == &h->n; |
|||
} |
|||
|
|||
/**
|
|||
* list_del - delete an entry from an (unknown) linked list. |
|||
* @n: the list_node to delete from the list. |
|||
* |
|||
* Note that this leaves @n in an undefined state; it can be added to |
|||
* another list, but not deleted again. |
|||
* |
|||
* See also: |
|||
* list_del_from(), list_del_init() |
|||
* |
|||
* Example: |
|||
* list_del(&child->list); |
|||
* parent->num_children--; |
|||
*/ |
|||
#define list_del(n) list_del_(n, LIST_LOC) |
|||
static inline void list_del_(struct list_node *n, const char* abortstr) |
|||
{ |
|||
(void)list_debug_node(n, abortstr); |
|||
n->next->prev = n->prev; |
|||
n->prev->next = n->next; |
|||
#ifdef CCAN_LIST_DEBUG |
|||
/* Catch use-after-del. */ |
|||
n->next = n->prev = NULL; |
|||
#endif |
|||
} |
|||
|
|||
/**
|
|||
* list_del_init - delete a node, and reset it so it can be deleted again. |
|||
* @n: the list_node to be deleted. |
|||
* |
|||
* list_del(@n) or list_del_init() again after this will be safe, |
|||
* which can be useful in some cases. |
|||
* |
|||
* See also: |
|||
* list_del_from(), list_del() |
|||
* |
|||
* Example: |
|||
* list_del_init(&child->list); |
|||
* parent->num_children--; |
|||
*/ |
|||
#define list_del_init(n) list_del_init_(n, LIST_LOC) |
|||
static inline void list_del_init_(struct list_node *n, const char *abortstr) |
|||
{ |
|||
list_del_(n, abortstr); |
|||
list_node_init(n); |
|||
} |
|||
|
|||
/**
|
|||
* list_del_from - delete an entry from a known linked list. |
|||
* @h: the list_head the node is in. |
|||
* @n: the list_node to delete from the list. |
|||
* |
|||
* This explicitly indicates which list a node is expected to be in, |
|||
* which is better documentation and can catch more bugs. |
|||
* |
|||
* See also: list_del() |
|||
* |
|||
* Example: |
|||
* list_del_from(&parent->children, &child->list); |
|||
* parent->num_children--; |
|||
*/ |
|||
static inline void list_del_from(struct list_head *h, struct list_node *n) |
|||
{ |
|||
#ifdef CCAN_LIST_DEBUG |
|||
{ |
|||
/* Thorough check: make sure it was in list! */ |
|||
struct list_node *i; |
|||
for (i = h->n.next; i != n; i = i->next) |
|||
assert(i != &h->n); |
|||
} |
|||
#endif /* CCAN_LIST_DEBUG */ |
|||
|
|||
/* Quick test that catches a surprising number of bugs. */ |
|||
assert(!list_empty(h)); |
|||
list_del(n); |
|||
} |
|||
|
|||
/**
|
|||
* list_swap - swap out an entry from an (unknown) linked list for a new one. |
|||
* @o: the list_node to replace from the list. |
|||
* @n: the list_node to insert in place of the old one. |
|||
* |
|||
* Note that this leaves @o in an undefined state; it can be added to |
|||
* another list, but not deleted/swapped again. |
|||
* |
|||
* See also: |
|||
* list_del() |
|||
* |
|||
* Example: |
|||
* struct child x1, x2; |
|||
* LIST_HEAD(xh); |
|||
* |
|||
* list_add(&xh, &x1.list); |
|||
* list_swap(&x1.list, &x2.list); |
|||
*/ |
|||
#define list_swap(o, n) list_swap_(o, n, LIST_LOC) |
|||
static inline void list_swap_(struct list_node *o, |
|||
struct list_node *n, |
|||
const char* abortstr) |
|||
{ |
|||
(void)list_debug_node(o, abortstr); |
|||
*n = *o; |
|||
n->next->prev = n; |
|||
n->prev->next = n; |
|||
#ifdef CCAN_LIST_DEBUG |
|||
/* Catch use-after-del. */ |
|||
o->next = o->prev = NULL; |
|||
#endif |
|||
} |
|||
|
|||
/**
|
|||
* list_entry - convert a list_node back into the structure containing it. |
|||
* @n: the list_node |
|||
* @type: the type of the entry |
|||
* @member: the list_node member of the type |
|||
* |
|||
* Example: |
|||
* // First list entry is children.next; convert back to child.
|
|||
* child = list_entry(parent->children.n.next, struct child, list); |
|||
* |
|||
* See Also: |
|||
* list_top(), list_for_each() |
|||
*/ |
|||
#define list_entry(n, type, member) container_of(n, type, member) |
|||
|
|||
/**
|
|||
* list_top - get the first entry in a list |
|||
* @h: the list_head |
|||
* @type: the type of the entry |
|||
* @member: the list_node member of the type |
|||
* |
|||
* If the list is empty, returns NULL. |
|||
* |
|||
* Example: |
|||
* struct child *first; |
|||
* first = list_top(&parent->children, struct child, list); |
|||
* if (!first) |
|||
* printf("Empty list!\n"); |
|||
*/ |
|||
#define list_top(h, type, member) \ |
|||
((type *)list_top_((h), list_off_(type, member))) |
|||
|
|||
static inline const void *list_top_(const struct list_head *h, size_t off) |
|||
{ |
|||
if (list_empty(h)) |
|||
return NULL; |
|||
return (const char *)h->n.next - off; |
|||
} |
|||
|
|||
/**
|
|||
* list_pop - remove the first entry in a list |
|||
* @h: the list_head |
|||
* @type: the type of the entry |
|||
* @member: the list_node member of the type |
|||
* |
|||
* If the list is empty, returns NULL. |
|||
* |
|||
* Example: |
|||
* struct child *one; |
|||
* one = list_pop(&parent->children, struct child, list); |
|||
* if (!one) |
|||
* printf("Empty list!\n"); |
|||
*/ |
|||
#define list_pop(h, type, member) \ |
|||
((type *)list_pop_((h), list_off_(type, member))) |
|||
|
|||
static inline const void *list_pop_(const struct list_head *h, size_t off) |
|||
{ |
|||
struct list_node *n; |
|||
|
|||
if (list_empty(h)) |
|||
return NULL; |
|||
n = h->n.next; |
|||
list_del(n); |
|||
return (const char *)n - off; |
|||
} |
|||
|
|||
/**
|
|||
* list_tail - get the last entry in a list |
|||
* @h: the list_head |
|||
* @type: the type of the entry |
|||
* @member: the list_node member of the type |
|||
* |
|||
* If the list is empty, returns NULL. |
|||
* |
|||
* Example: |
|||
* struct child *last; |
|||
* last = list_tail(&parent->children, struct child, list); |
|||
* if (!last) |
|||
* printf("Empty list!\n"); |
|||
*/ |
|||
#define list_tail(h, type, member) \ |
|||
((type *)list_tail_((h), list_off_(type, member))) |
|||
|
|||
static inline const void *list_tail_(const struct list_head *h, size_t off) |
|||
{ |
|||
if (list_empty(h)) |
|||
return NULL; |
|||
return (const char *)h->n.prev - off; |
|||
} |
|||
|
|||
/**
|
|||
* list_for_each - iterate through a list. |
|||
* @h: the list_head (warning: evaluated multiple times!) |
|||
* @i: the structure containing the list_node |
|||
* @member: the list_node member of the structure |
|||
* |
|||
* This is a convenient wrapper to iterate @i over the entire list. It's |
|||
* a for loop, so you can break and continue as normal. |
|||
* |
|||
* Example: |
|||
* list_for_each(&parent->children, child, list) |
|||
* printf("Name: %s\n", child->name); |
|||
*/ |
|||
#define list_for_each(h, i, member) \ |
|||
list_for_each_off(h, i, list_off_var_(i, member)) |
|||
|
|||
/**
|
|||
* list_for_each_rev - iterate through a list backwards. |
|||
* @h: the list_head |
|||
* @i: the structure containing the list_node |
|||
* @member: the list_node member of the structure |
|||
* |
|||
* This is a convenient wrapper to iterate @i over the entire list. It's |
|||
* a for loop, so you can break and continue as normal. |
|||
* |
|||
* Example: |
|||
* list_for_each_rev(&parent->children, child, list) |
|||
* printf("Name: %s\n", child->name); |
|||
*/ |
|||
#define list_for_each_rev(h, i, member) \ |
|||
list_for_each_rev_off(h, i, list_off_var_(i, member)) |
|||
|
|||
/**
|
|||
* list_for_each_rev_safe - iterate through a list backwards, |
|||
* maybe during deletion |
|||
* @h: the list_head |
|||
* @i: the structure containing the list_node |
|||
* @nxt: the structure containing the list_node |
|||
* @member: the list_node member of the structure |
|||
* |
|||
* This is a convenient wrapper to iterate @i over the entire list backwards. |
|||
* It's a for loop, so you can break and continue as normal. The extra |
|||
* variable * @nxt is used to hold the next element, so you can delete @i |
|||
* from the list. |
|||
* |
|||
* Example: |
|||
* struct child *next; |
|||
* list_for_each_rev_safe(&parent->children, child, next, list) { |
|||
* printf("Name: %s\n", child->name); |
|||
* } |
|||
*/ |
|||
#define list_for_each_rev_safe(h, i, nxt, member) \ |
|||
list_for_each_rev_safe_off(h, i, nxt, list_off_var_(i, member)) |
|||
|
|||
/**
|
|||
* list_for_each_safe - iterate through a list, maybe during deletion |
|||
* @h: the list_head |
|||
* @i: the structure containing the list_node |
|||
* @nxt: the structure containing the list_node |
|||
* @member: the list_node member of the structure |
|||
* |
|||
* This is a convenient wrapper to iterate @i over the entire list. It's |
|||
* a for loop, so you can break and continue as normal. The extra variable |
|||
* @nxt is used to hold the next element, so you can delete @i from the list. |
|||
* |
|||
* Example: |
|||
* list_for_each_safe(&parent->children, child, next, list) { |
|||
* list_del(&child->list); |
|||
* parent->num_children--; |
|||
* } |
|||
*/ |
|||
#define list_for_each_safe(h, i, nxt, member) \ |
|||
list_for_each_safe_off(h, i, nxt, list_off_var_(i, member)) |
|||
|
|||
/**
|
|||
* list_next - get the next entry in a list |
|||
* @h: the list_head |
|||
* @i: a pointer to an entry in the list. |
|||
* @member: the list_node member of the structure |
|||
* |
|||
* If @i was the last entry in the list, returns NULL. |
|||
* |
|||
* Example: |
|||
* struct child *second; |
|||
* second = list_next(&parent->children, first, list); |
|||
* if (!second) |
|||
* printf("No second child!\n"); |
|||
*/ |
|||
#define list_next(h, i, member) \ |
|||
((list_typeof(i))list_entry_or_null(list_debug(h, \ |
|||
__FILE__ ":" stringify(__LINE__)), \ |
|||
(i)->member.next, \ |
|||
list_off_var_((i), member))) |
|||
|
|||
/**
|
|||
* list_prev - get the previous entry in a list |
|||
* @h: the list_head |
|||
* @i: a pointer to an entry in the list. |
|||
* @member: the list_node member of the structure |
|||
* |
|||
* If @i was the first entry in the list, returns NULL. |
|||
* |
|||
* Example: |
|||
* first = list_prev(&parent->children, second, list); |
|||
* if (!first) |
|||
* printf("Can't go back to first child?!\n"); |
|||
*/ |
|||
#define list_prev(h, i, member) \ |
|||
((list_typeof(i))list_entry_or_null(list_debug(h, \ |
|||
__FILE__ ":" stringify(__LINE__)), \ |
|||
(i)->member.prev, \ |
|||
list_off_var_((i), member))) |
|||
|
|||
/**
|
|||
* list_append_list - empty one list onto the end of another. |
|||
* @to: the list to append into |
|||
* @from: the list to empty. |
|||
* |
|||
* This takes the entire contents of @from and moves it to the end of |
|||
* @to. After this @from will be empty. |
|||
* |
|||
* Example: |
|||
* struct list_head adopter; |
|||
* |
|||
* list_append_list(&adopter, &parent->children); |
|||
* assert(list_empty(&parent->children)); |
|||
* parent->num_children = 0; |
|||
*/ |
|||
#define list_append_list(t, f) list_append_list_(t, f, \ |
|||
__FILE__ ":" stringify(__LINE__)) |
|||
static inline void list_append_list_(struct list_head *to, |
|||
struct list_head *from, |
|||
const char *abortstr) |
|||
{ |
|||
struct list_node *from_tail = list_debug(from, abortstr)->n.prev; |
|||
struct list_node *to_tail = list_debug(to, abortstr)->n.prev; |
|||
|
|||
/* Sew in head and entire list. */ |
|||
to->n.prev = from_tail; |
|||
from_tail->next = &to->n; |
|||
to_tail->next = &from->n; |
|||
from->n.prev = to_tail; |
|||
|
|||
/* Now remove head. */ |
|||
list_del(&from->n); |
|||
list_head_init(from); |
|||
} |
|||
|
|||
/**
|
|||
* list_prepend_list - empty one list into the start of another. |
|||
* @to: the list to prepend into |
|||
* @from: the list to empty. |
|||
* |
|||
* This takes the entire contents of @from and moves it to the start |
|||
* of @to. After this @from will be empty. |
|||
* |
|||
* Example: |
|||
* list_prepend_list(&adopter, &parent->children); |
|||
* assert(list_empty(&parent->children)); |
|||
* parent->num_children = 0; |
|||
*/ |
|||
#define list_prepend_list(t, f) list_prepend_list_(t, f, LIST_LOC) |
|||
static inline void list_prepend_list_(struct list_head *to, |
|||
struct list_head *from, |
|||
const char *abortstr) |
|||
{ |
|||
struct list_node *from_tail = list_debug(from, abortstr)->n.prev; |
|||
struct list_node *to_head = list_debug(to, abortstr)->n.next; |
|||
|
|||
/* Sew in head and entire list. */ |
|||
to->n.next = &from->n; |
|||
from->n.prev = &to->n; |
|||
to_head->prev = from_tail; |
|||
from_tail->next = to_head; |
|||
|
|||
/* Now remove head. */ |
|||
list_del(&from->n); |
|||
list_head_init(from); |
|||
} |
|||
|
|||
/* internal macros, do not use directly */ |
|||
#define list_for_each_off_dir_(h, i, off, dir) \ |
|||
for (i = list_node_to_off_(list_debug(h, LIST_LOC)->n.dir, \ |
|||
(off)); \ |
|||
list_node_from_off_((void *)i, (off)) != &(h)->n; \ |
|||
i = list_node_to_off_(list_node_from_off_((void *)i, (off))->dir, \ |
|||
(off))) |
|||
|
|||
#define list_for_each_safe_off_dir_(h, i, nxt, off, dir) \ |
|||
for (i = list_node_to_off_(list_debug(h, LIST_LOC)->n.dir, \ |
|||
(off)), \ |
|||
nxt = list_node_to_off_(list_node_from_off_(i, (off))->dir, \ |
|||
(off)); \ |
|||
list_node_from_off_(i, (off)) != &(h)->n; \ |
|||
i = nxt, \ |
|||
nxt = list_node_to_off_(list_node_from_off_(i, (off))->dir, \ |
|||
(off))) |
|||
|
|||
/**
|
|||
* list_for_each_off - iterate through a list of memory regions. |
|||
* @h: the list_head |
|||
* @i: the pointer to a memory region which contains list node data. |
|||
* @off: offset(relative to @i) at which list node data resides. |
|||
* |
|||
* This is a low-level wrapper to iterate @i over the entire list, used to |
|||
* implement all oher, more high-level, for-each constructs. It's a for loop, |
|||
* so you can break and continue as normal. |
|||
* |
|||
* WARNING! Being the low-level macro that it is, this wrapper doesn't know |
|||
* nor care about the type of @i. The only assumption made is that @i points |
|||
* to a chunk of memory that at some @offset, relative to @i, contains a |
|||
* properly filled `struct list_node' which in turn contains pointers to |
|||
* memory chunks and it's turtles all the way down. With all that in mind |
|||
* remember that given the wrong pointer/offset couple this macro will |
|||
* happily churn all you memory until SEGFAULT stops it, in other words |
|||
* caveat emptor. |
|||
* |
|||
* It is worth mentioning that one of legitimate use-cases for that wrapper |
|||
* is operation on opaque types with known offset for `struct list_node' |
|||
* member(preferably 0), because it allows you not to disclose the type of |
|||
* @i. |
|||
* |
|||
* Example: |
|||
* list_for_each_off(&parent->children, child, |
|||
* offsetof(struct child, list)) |
|||
* printf("Name: %s\n", child->name); |
|||
*/ |
|||
#define list_for_each_off(h, i, off) \ |
|||
list_for_each_off_dir_((h),(i),(off),next) |
|||
|
|||
/**
|
|||
* list_for_each_rev_off - iterate through a list of memory regions backwards |
|||
* @h: the list_head |
|||
* @i: the pointer to a memory region which contains list node data. |
|||
* @off: offset(relative to @i) at which list node data resides. |
|||
* |
|||
* See list_for_each_off for details |
|||
*/ |
|||
#define list_for_each_rev_off(h, i, off) \ |
|||
list_for_each_off_dir_((h),(i),(off),prev) |
|||
|
|||
/**
|
|||
* list_for_each_safe_off - iterate through a list of memory regions, maybe |
|||
* during deletion |
|||
* @h: the list_head |
|||
* @i: the pointer to a memory region which contains list node data. |
|||
* @nxt: the structure containing the list_node |
|||
* @off: offset(relative to @i) at which list node data resides. |
|||
* |
|||
* For details see `list_for_each_off' and `list_for_each_safe' |
|||
* descriptions. |
|||
* |
|||
* Example: |
|||
* list_for_each_safe_off(&parent->children, child, |
|||
* next, offsetof(struct child, list)) |
|||
* printf("Name: %s\n", child->name); |
|||
*/ |
|||
#define list_for_each_safe_off(h, i, nxt, off) \ |
|||
list_for_each_safe_off_dir_((h),(i),(nxt),(off),next) |
|||
|
|||
/**
|
|||
* list_for_each_rev_safe_off - iterate backwards through a list of |
|||
* memory regions, maybe during deletion |
|||
* @h: the list_head |
|||
* @i: the pointer to a memory region which contains list node data. |
|||
* @nxt: the structure containing the list_node |
|||
* @off: offset(relative to @i) at which list node data resides. |
|||
* |
|||
* For details see `list_for_each_rev_off' and `list_for_each_rev_safe' |
|||
* descriptions. |
|||
* |
|||
* Example: |
|||
* list_for_each_rev_safe_off(&parent->children, child, |
|||
* next, offsetof(struct child, list)) |
|||
* printf("Name: %s\n", child->name); |
|||
*/ |
|||
#define list_for_each_rev_safe_off(h, i, nxt, off) \ |
|||
list_for_each_safe_off_dir_((h),(i),(nxt),(off),prev) |
|||
|
|||
/* Other -off variants. */ |
|||
#define list_entry_off(n, type, off) \ |
|||
((type *)list_node_from_off_((n), (off))) |
|||
|
|||
#define list_head_off(h, type, off) \ |
|||
((type *)list_head_off((h), (off))) |
|||
|
|||
#define list_tail_off(h, type, off) \ |
|||
((type *)list_tail_((h), (off))) |
|||
|
|||
#define list_add_off(h, n, off) \ |
|||
list_add((h), list_node_from_off_((n), (off))) |
|||
|
|||
#define list_del_off(n, off) \ |
|||
list_del(list_node_from_off_((n), (off))) |
|||
|
|||
#define list_del_from_off(h, n, off) \ |
|||
list_del_from(h, list_node_from_off_((n), (off))) |
|||
|
|||
/* Offset helper functions so we only single-evaluate. */ |
|||
static inline void *list_node_to_off_(struct list_node *node, size_t off) |
|||
{ |
|||
return (void *)((char *)node - off); |
|||
} |
|||
static inline struct list_node *list_node_from_off_(void *ptr, size_t off) |
|||
{ |
|||
return (struct list_node *)((char *)ptr + off); |
|||
} |
|||
|
|||
/* Get the offset of the member, but make sure it's a list_node. */ |
|||
#define list_off_(type, member) \ |
|||
(container_off(type, member) + \ |
|||
check_type(((type *)0)->member, struct list_node)) |
|||
|
|||
#define list_off_var_(var, member) \ |
|||
(container_off_var(var, member) + \ |
|||
check_type(var->member, struct list_node)) |
|||
|
|||
#if HAVE_TYPEOF |
|||
#define list_typeof(var) typeof(var) |
|||
#else |
|||
#define list_typeof(var) void * |
|||
#endif |
|||
|
|||
/* Returns member, or NULL if at end of list. */ |
|||
static inline void *list_entry_or_null(const struct list_head *h, |
|||
const struct list_node *n, |
|||
size_t off) |
|||
{ |
|||
if (n == &h->n) |
|||
return NULL; |
|||
return (char *)n - off; |
|||
} |
|||
#endif /* CCAN_LIST_H */ |
@ -0,0 +1,128 @@ |
|||
/* CC0 (Public domain) - see LICENSE file for details */ |
|||
|
|||
#include "config.h" |
|||
|
|||
#include <assert.h> |
|||
#include <string.h> |
|||
#include "mem.h" |
|||
|
|||
#if !HAVE_MEMMEM |
|||
void *memmem(const void *haystack, size_t haystacklen, |
|||
const void *needle, size_t needlelen) |
|||
{ |
|||
const char *p; |
|||
|
|||
if (needlelen > haystacklen) |
|||
return NULL; |
|||
|
|||
p = haystack; |
|||
|
|||
for (p = haystack; |
|||
(p + needlelen) <= ((const char *)haystack + haystacklen); |
|||
p++) |
|||
if (memcmp(p, needle, needlelen) == 0) |
|||
return (void *)p; |
|||
|
|||
return NULL; |
|||
} |
|||
#endif |
|||
|
|||
#if !HAVE_MEMRCHR |
|||
void *memrchr(const void *s, int c, size_t n) |
|||
{ |
|||
unsigned char *p = (unsigned char *)s; |
|||
|
|||
while (n) { |
|||
if (p[n-1] == c) |
|||
return p + n - 1; |
|||
n--; |
|||
} |
|||
|
|||
return NULL; |
|||
} |
|||
#endif |
|||
|
|||
void *mempbrkm(const void *data_, size_t len, const void *accept_, size_t accept_len) |
|||
{ |
|||
const char *data = data_, *accept = accept_; |
|||
size_t i, j; |
|||
|
|||
for (i = 0; i < len; i++) |
|||
for (j = 0; j < accept_len; j++) |
|||
if (accept[j] == data[i]) |
|||
return (void *)&data[i]; |
|||
return NULL; |
|||
} |
|||
|
|||
void *memcchr(void const *data, int c, size_t data_len) |
|||
{ |
|||
char const *p = data; |
|||
size_t i; |
|||
|
|||
for (i = 0; i < data_len; i++) |
|||
if (p[i] != c) |
|||
return (void *)&p[i]; |
|||
|
|||
return NULL; |
|||
} |
|||
|
|||
#define MEMSWAP_TMP_SIZE 256 |
|||
|
|||
void memswap(void *a, void *b, size_t n) |
|||
{ |
|||
char *ap = a; |
|||
char *bp = b; |
|||
char tmp[MEMSWAP_TMP_SIZE]; |
|||
|
|||
assert(!memoverlaps(a, n, b, n)); |
|||
|
|||
while (n) { |
|||
size_t m = n > MEMSWAP_TMP_SIZE ? MEMSWAP_TMP_SIZE : n; |
|||
|
|||
memcpy(tmp, bp, m); |
|||
memcpy(bp, ap, m); |
|||
memcpy(ap, tmp, m); |
|||
|
|||
ap += m; |
|||
bp += m; |
|||
n -= m; |
|||
} |
|||
} |
|||
|
|||
bool memeqzero(const void *data, size_t length) |
|||
{ |
|||
const unsigned char *p = data; |
|||
size_t len; |
|||
|
|||
/* Check first 16 bytes manually */ |
|||
for (len = 0; len < 16; len++) { |
|||
if (!length) |
|||
return true; |
|||
if (*p) |
|||
return false; |
|||
p++; |
|||
length--; |
|||
} |
|||
|
|||
/* Now we know that's zero, memcmp with self. */ |
|||
return memcmp(data, p, length) == 0; |
|||
} |
|||
|
|||
void memtaint(void *data, size_t len) |
|||
{ |
|||
/* Using 16 bytes is a bit quicker than 4 */ |
|||
const unsigned tainter[] |
|||
= { 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef }; |
|||
char *p = data; |
|||
|
|||
while (len >= sizeof(tainter)) { |
|||
memcpy(p, tainter, sizeof(tainter)); |
|||
p += sizeof(tainter); |
|||
len -= sizeof(tainter); |
|||
} |
|||
memcpy(p, tainter, len); |
|||
|
|||
#if HAVE_VALGRIND_MEMCHECK_H |
|||
VALGRIND_MAKE_MEM_UNDEFINED(data, len); |
|||
#endif |
|||
} |
@ -0,0 +1,295 @@ |
|||
/* CC0 (Public domain) - see LICENSE file for details */ |
|||
#ifndef CCAN_MEM_H |
|||
#define CCAN_MEM_H |
|||
|
|||
#include "config.h" |
|||
#include "compiler.h" |
|||
|
|||
#include <string.h> |
|||
#include <stdbool.h> |
|||
|
|||
#if !HAVE_MEMMEM |
|||
PURE_FUNCTION |
|||
void *memmem(const void *haystack, size_t haystacklen, |
|||
const void *needle, size_t needlelen); |
|||
#endif |
|||
|
|||
#if !HAVE_MEMRCHR |
|||
PURE_FUNCTION |
|||
void *memrchr(const void *s, int c, size_t n); |
|||
#endif |
|||
|
|||
/**
|
|||
* mempbrkm - locates the first occurrence in @data of any bytes in @accept |
|||
* @data: where we search |
|||
* @len: length of data in bytes |
|||
* @accept: array of bytes we search for |
|||
* @accept_len: # of bytes in accept |
|||
* |
|||
* Returns a pointer to the byte in @data that matches one of the bytes in |
|||
* @accept, or NULL if no such byte is found. |
|||
* |
|||
* Example: |
|||
* char otherbytes[] = "Hello \0world"; |
|||
* size_t otherbytes_len = sizeof(otherbytes) - 1; |
|||
* char *r = mempbrkm(otherbytes, otherbytes_len, "\0b", 2); |
|||
* if (r) { |
|||
* printf("Found %c\n", *r); |
|||
* } else { |
|||
* printf("Nada\n"); |
|||
* } |
|||
* |
|||
*/ |
|||
PURE_FUNCTION |
|||
void *mempbrkm(const void *data, size_t len, const void *accept, size_t accept_len); |
|||
|
|||
/**
|
|||
* mempbrk - locates the first occurrence in @data of any bytes in @accept |
|||
* @data: where we search |
|||
* @len: length of data in bytes |
|||
* @accept: NUL terminated string containing the bytes we search for |
|||
* |
|||
* Returns a pointer to the byte in @data that matches one of the bytes in |
|||
* @accept, or NULL if no such byte is found. |
|||
* |
|||
* Example: |
|||
* |
|||
* r = mempbrk(otherbytes, otherbytes_len, "abcde"); |
|||
* if (r) { |
|||
* printf("Found %c\n", *r); |
|||
* } else { |
|||
* printf("Nada\n"); |
|||
* } |
|||
*/ |
|||
PURE_FUNCTION |
|||
static inline char *mempbrk(const void *data, size_t len, const char *accept) |
|||
{ |
|||
return mempbrkm(data, len, accept, strlen(accept)); |
|||
} |
|||
|
|||
/**
|
|||
* memcchr - scan memory until a character does _not_ match |
|||
* @data: pointer to memory to scan |
|||
* @data_len: length of data |
|||
* @c: character to scan for |
|||
* |
|||
* The complement of memchr(). |
|||
* |
|||
* Returns a pointer to the first character which is _not_ @c. If all memory in |
|||
* @data is @c, returns NULL. |
|||
* |
|||
* Example: |
|||
* char somebytes[] = "HI By\0e"; |
|||
* size_t bytes_len = sizeof(somebytes) - 1; |
|||
* r = memcchr(somebytes, ' ', bytes_len); |
|||
* if (r) { |
|||
* printf("Found %c after trimming spaces\n", *r); |
|||
* } |
|||
*/ |
|||
PURE_FUNCTION |
|||
void *memcchr(void const *data, int c, size_t data_len); |
|||
|
|||
/**
|
|||
* memeq - Are two byte arrays equal? |
|||
* @a: first array |
|||
* @al: bytes in first array |
|||
* @b: second array |
|||
* @bl: bytes in second array |
|||
* |
|||
* Example: |
|||
* if (memeq(somebytes, bytes_len, otherbytes, otherbytes_len)) { |
|||
* printf("memory blocks are the same!\n"); |
|||
* } |
|||
*/ |
|||
PURE_FUNCTION |
|||
static inline bool memeq(const void *a, size_t al, const void *b, size_t bl) |
|||
{ |
|||
return al == bl && !memcmp(a, b, bl); |
|||
} |
|||
|
|||
/**
|
|||
* memstarts - determine if @data starts with @prefix |
|||
* @data: does this begin with @prefix? |
|||
* @data_len: bytes in @data |
|||
* @prefix: does @data begin with these bytes? |
|||
* @prefix_len: bytes in @prefix |
|||
* |
|||
* Returns true if @data starts with @prefix, otherwise return false. |
|||
* |
|||
* Example: |
|||
* if (memstarts(somebytes, bytes_len, otherbytes, otherbytes_len)) { |
|||
* printf("somebytes starts with otherbytes!\n"); |
|||
* } |
|||
*/ |
|||
PURE_FUNCTION |
|||
static inline bool memstarts(void const *data, size_t data_len, |
|||
void const *prefix, size_t prefix_len) |
|||
{ |
|||
if (prefix_len > data_len) |
|||
return false; |
|||
return memeq(data, prefix_len, prefix, prefix_len); |
|||
} |
|||
|
|||
/**
|
|||
* memeqstr - Is a byte array equal to a NUL terminated string? |
|||
* @data: byte array |
|||
* @length: length of @data in bytes |
|||
* @string: NUL terminated string |
|||
* |
|||
* The '\0' byte is ignored when checking if @bytes == @string. |
|||
* |
|||
* Example: |
|||
* if (memeqstr(somebytes, bytes_len, "foo")) { |
|||
* printf("somebytes == 'foo'!\n"); |
|||
* } |
|||
*/ |
|||
PURE_FUNCTION |
|||
static inline bool memeqstr(const void *data, size_t length, const char *string) |
|||
{ |
|||
return memeq(data, length, string, strlen(string)); |
|||
} |
|||
|
|||
/**
|
|||
* memeqzero - Is a byte array all zeroes? |
|||
* @data: byte array |
|||
* @length: length of @data in bytes |
|||
* |
|||
* Example: |
|||
* if (memeqzero(somebytes, bytes_len)) { |
|||
* printf("somebytes == 0!\n"); |
|||
* } |
|||
*/ |
|||
PURE_FUNCTION |
|||
bool memeqzero(const void *data, size_t length); |
|||
|
|||
/**
|
|||
* memstarts_str - Does this byte array start with a string prefix? |
|||
* @a: byte array |
|||
* @al: length in bytes |
|||
* @s: string prefix |
|||
* |
|||
* Example: |
|||
* if (memstarts_str(somebytes, bytes_len, "It")) { |
|||
* printf("somebytes starts with 'It'\n"); |
|||
* } |
|||
*/ |
|||
PURE_FUNCTION |
|||
static inline bool memstarts_str(const void *a, size_t al, const char *s) |
|||
{ |
|||
return memstarts(a, al, s, strlen(s)); |
|||
} |
|||
|
|||
/**
|
|||
* memends - Does this byte array end with a given byte-array suffix? |
|||
* @s: byte array |
|||
* @s_len: length in bytes |
|||
* @suffix: byte array suffix |
|||
* @suffix_len: length of suffix in bytes |
|||
* |
|||
* Returns true if @suffix appears as a substring at the end of @s, |
|||
* false otherwise. |
|||
*/ |
|||
PURE_FUNCTION |
|||
static inline bool memends(const void *s, size_t s_len, const void *suffix, size_t suffix_len) |
|||
{ |
|||
return (s_len >= suffix_len) && (memcmp((const char *)s + s_len - suffix_len, |
|||
suffix, suffix_len) == 0); |
|||
} |
|||
|
|||
/**
|
|||
* memends_str - Does this byte array end with a string suffix? |
|||
* @a: byte array |
|||
* @al: length in bytes |
|||
* @s: string suffix |
|||
* |
|||
* Example: |
|||
* if (memends_str(somebytes, bytes_len, "It")) { |
|||
* printf("somebytes ends with with 'It'\n"); |
|||
* } |
|||
*/ |
|||
PURE_FUNCTION |
|||
static inline bool memends_str(const void *a, size_t al, const char *s) |
|||
{ |
|||
return memends(a, al, s, strlen(s)); |
|||
} |
|||
|
|||
/**
|
|||
* memoverlaps - Do two memory ranges overlap? |
|||
* @a: pointer to first memory range |
|||
* @al: length of first memory range |
|||
* @b: pointer to second memory range |
|||
* @al: length of second memory range |
|||
*/ |
|||
CONST_FUNCTION |
|||
static inline bool memoverlaps(const void *a_, size_t al, |
|||
const void *b_, size_t bl) |
|||
{ |
|||
const char *a = a_; |
|||
const char *b = b_; |
|||
|
|||
return (a < (b + bl)) && (b < (a + al)); |
|||
} |
|||
|
|||
/*
|
|||
* memswap - Exchange two memory regions |
|||
* @a: first region |
|||
* @b: second region |
|||
* @n: length of the regions |
|||
* |
|||
* Undefined results if the two memory regions overlap. |
|||
*/ |
|||
void memswap(void *a, void *b, size_t n); |
|||
|
|||
#if HAVE_VALGRIND_MEMCHECK_H |
|||
#include <valgrind/memcheck.h> |
|||
static inline void *memcheck_(const void *data, size_t len) |
|||
{ |
|||
VALGRIND_CHECK_MEM_IS_DEFINED(data, len); |
|||
return (void *)data; |
|||
} |
|||
#else |
|||
static inline void *memcheck_(const void *data, size_t len) |
|||
{ |
|||
(void)len; |
|||
return (void *)data; |
|||
} |
|||
#endif |
|||
|
|||
#if HAVE_TYPEOF |
|||
/**
|
|||
* memcheck - check that a memory region is initialized |
|||
* @data: start of region |
|||
* @len: length in bytes |
|||
* |
|||
* When running under valgrind, this causes an error to be printed |
|||
* if the entire region is not defined. Otherwise valgrind only |
|||
* reports an error when an undefined value is used for a branch, or |
|||
* written out. |
|||
* |
|||
* Example: |
|||
* // Search for space, but make sure it's all initialized.
|
|||
* if (memchr(memcheck(somebytes, bytes_len), ' ', bytes_len)) { |
|||
* printf("space was found!\n"); |
|||
* } |
|||
*/ |
|||
#define memcheck(data, len) ((__typeof__((data)+0))memcheck_((data), (len))) |
|||
#else |
|||
#define memcheck(data, len) memcheck_((data), (len)) |
|||
#endif |
|||
|
|||
/**
|
|||
* memtaint - mark a memory region unused |
|||
* @data: start of region |
|||
* @len: length in bytes |
|||
* |
|||
* This writes an "0xdeadbeef" eyecatcher repeatedly to the memory. |
|||
* When running under valgrind, it also tells valgrind that the memory is |
|||
* uninitialized, triggering valgrind errors if it is used for branches |
|||
* or written out (or passed to memcheck!) in future. |
|||
* |
|||
* Example: |
|||
* // We'll reuse this buffer later, but be sure we don't access it.
|
|||
* memtaint(somebytes, bytes_len); |
|||
*/ |
|||
void memtaint(void *data, size_t len); |
|||
#endif /* CCAN_MEM_H */ |
@ -0,0 +1,64 @@ |
|||
#include "config.h" |
|||
#include <assert.h> |
|||
#include "array_size.h" |
|||
#include "mem.h" |
|||
#include "hex.h" |
|||
#include "talstr.h" |
|||
#include "node_id.h" |
|||
|
|||
/* Convert from pubkey to compressed pubkey. */ |
|||
/*
|
|||
void node_id_from_pubkey(struct node_id *id, const struct pubkey *key) |
|||
{ |
|||
size_t outlen = ARRAY_SIZE(id->k); |
|||
if (!secp256k1_ec_pubkey_serialize(secp256k1_ctx, id->k, &outlen, |
|||
&key->pubkey, |
|||
SECP256K1_EC_COMPRESSED)) |
|||
abort(); |
|||
} |
|||
|
|||
WARN_UNUSED_RESULT |
|||
bool pubkey_from_node_id(struct pubkey *key, const struct node_id *id) |
|||
{ |
|||
return secp256k1_ec_pubkey_parse(secp256k1_ctx, &key->pubkey, |
|||
memcheck(id->k, sizeof(id->k)), |
|||
sizeof(id->k)); |
|||
} |
|||
|
|||
WARN_UNUSED_RESULT |
|||
bool point32_from_node_id(struct point32 *key, const struct node_id *id) |
|||
{ |
|||
struct pubkey k; |
|||
if (!pubkey_from_node_id(&k, id)) |
|||
return false; |
|||
return secp256k1_xonly_pubkey_from_pubkey(secp256k1_ctx, &key->pubkey, |
|||
NULL, &k.pubkey) == 1; |
|||
} |
|||
*/ |
|||
|
|||
char *tal_hexstr(const tal_t *ctx, const void *data, size_t len) |
|||
{ |
|||
char *str = tal_arr(ctx, char, hex_str_size(len)); |
|||
hex_encode(data, len, str, hex_str_size(len)); |
|||
return str; |
|||
} |
|||
|
|||
|
|||
/* Convert to hex string of SEC1 encoding */ |
|||
char *node_id_to_hexstr(const tal_t *ctx, const struct node_id *id) |
|||
{ |
|||
return tal_hexstr(ctx, id->k, sizeof(id->k)); |
|||
} |
|||
|
|||
/* Convert from hex string of SEC1 encoding */ |
|||
|
|||
bool node_id_from_hexstr(const char *str, size_t slen, struct node_id *id) |
|||
{ |
|||
return hex_decode(str, slen, id->k, sizeof(id->k)); |
|||
/* && node_id_valid(id);*/ |
|||
} |
|||
|
|||
int node_id_cmp(const struct node_id *a, const struct node_id *b) |
|||
{ |
|||
return memcmp(a->k, b->k, sizeof(a->k)); |
|||
} |
@ -0,0 +1,38 @@ |
|||
/* Encapsulation for pubkeys used as node ids: more compact, more dangerous. */ |
|||
#ifndef LIGHTNING_COMMON_NODE_ID_H |
|||
#define LIGHTNING_COMMON_NODE_ID_H |
|||
#include "config.h" |
|||
#include "short_types.h" |
|||
#include "tal.h" |
|||
|
|||
struct node_id { |
|||
u8 k[33]; |
|||
}; |
|||
|
|||
static inline bool node_id_eq(const struct node_id *a, |
|||
const struct node_id *b) |
|||
{ |
|||
return memcmp(a->k, b->k, sizeof(a->k)) == 0; |
|||
} |
|||
|
|||
/* Is this actually a valid pubkey? Relatively expensive. */ |
|||
//bool node_id_valid(const struct node_id *id);
|
|||
|
|||
/* Convert to hex string of SEC1 encoding. */ |
|||
char *node_id_to_hexstr(const tal_t *ctx, const struct node_id *id); |
|||
|
|||
/* Convert from hex string of SEC1 encoding: checks validity! */ |
|||
bool node_id_from_hexstr(const char *str, size_t slen, struct node_id *id); |
|||
|
|||
/* Compare the keys `a` and `b`. Return <0 if `a`<`b`, 0 if equal and >0 otherwise */ |
|||
int node_id_cmp(const struct node_id *a, const struct node_id *b); |
|||
|
|||
/* If the two nodes[] are id1 and id2, which index would id1 be? */ |
|||
static inline int node_id_idx(const struct node_id *id1, |
|||
const struct node_id *id2) |
|||
{ |
|||
return node_id_cmp(id1, id2) > 0; |
|||
} |
|||
|
|||
/* marshal/unmarshal functions */ |
|||
#endif /* LIGHTNING_COMMON_NODE_ID_H */ |
@ -0,0 +1,43 @@ |
|||
#ifndef LIGHTNING_COMMON_OVERFLOWS_H |
|||
#define LIGHTNING_COMMON_OVERFLOWS_H |
|||
#include "config.h" |
|||
#include "short_types.h" |
|||
|
|||
static inline bool add_overflows_size_t(uint64_t a, uint64_t b) |
|||
{ |
|||
return (size_t)a != a || (size_t)b != b || (a + b) < (size_t)a; |
|||
} |
|||
|
|||
static inline bool add_overflows_u64(uint64_t a, uint64_t b) |
|||
{ |
|||
return (a + b) < a; |
|||
} |
|||
|
|||
static inline bool mul_overflows_u64(uint64_t a, uint64_t b) |
|||
{ |
|||
uint64_t ret; |
|||
|
|||
if (a == 0) |
|||
return false; |
|||
ret = a * b; |
|||
return (ret / a != b); |
|||
} |
|||
|
|||
static inline bool assign_overflow_u8(u8 *dst, uint64_t v) |
|||
{ |
|||
*dst = v; |
|||
return *dst == v; |
|||
} |
|||
|
|||
static inline bool assign_overflow_u16(u16 *dst, uint64_t v) |
|||
{ |
|||
*dst = v; |
|||
return *dst == v; |
|||
} |
|||
|
|||
static inline bool assign_overflow_u32(u32 *dst, uint64_t v) |
|||
{ |
|||
*dst = v; |
|||
return *dst == v; |
|||
} |
|||
#endif /* LIGHTNING_COMMON_OVERFLOWS_H */ |
@ -0,0 +1,308 @@ |
|||
/* MIT (BSD) license - see LICENSE file for details */ |
|||
/* SHA256 core code translated from the Bitcoin project's C++:
|
|||
* |
|||
* src/crypto/sha256.cpp commit 417532c8acb93c36c2b6fd052b7c11b6a2906aa2 |
|||
* Copyright (c) 2014 The Bitcoin Core developers |
|||
* Distributed under the MIT software license, see the accompanying |
|||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|||
*/ |
|||
#include "sha256.h" |
|||
#include "compiler.h" |
|||
#include "endian.h" |
|||
#include <stdbool.h> |
|||
#include <assert.h> |
|||
#include <string.h> |
|||
|
|||
static void invalidate_sha256(struct sha256_ctx *ctx) |
|||
{ |
|||
#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL |
|||
ctx->c.md_len = 0; |
|||
#else |
|||
ctx->bytes = (size_t)-1; |
|||
#endif |
|||
} |
|||
|
|||
static void check_sha256(struct sha256_ctx *ctx UNUSED) |
|||
{ |
|||
#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL |
|||
assert(ctx->c.md_len != 0); |
|||
#else |
|||
assert(ctx->bytes != (size_t)-1); |
|||
#endif |
|||
} |
|||
|
|||
#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL |
|||
void sha256_init(struct sha256_ctx *ctx) |
|||
{ |
|||
SHA256_Init(&ctx->c); |
|||
} |
|||
|
|||
void sha256_update(struct sha256_ctx *ctx, const void *p, size_t size) |
|||
{ |
|||
check_sha256(ctx); |
|||
SHA256_Update(&ctx->c, p, size); |
|||
} |
|||
|
|||
void sha256_done(struct sha256_ctx *ctx, struct sha256 *res) |
|||
{ |
|||
SHA256_Final(res->u.u8, &ctx->c); |
|||
invalidate_sha256(ctx); |
|||
} |
|||
#else |
|||
static uint32_t Ch(uint32_t x, uint32_t y, uint32_t z) |
|||
{ |
|||
return z ^ (x & (y ^ z)); |
|||
} |
|||
static uint32_t Maj(uint32_t x, uint32_t y, uint32_t z) |
|||
{ |
|||
return (x & y) | (z & (x | y)); |
|||
} |
|||
static uint32_t Sigma0(uint32_t x) |
|||
{ |
|||
return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10); |
|||
} |
|||
static uint32_t Sigma1(uint32_t x) |
|||
{ |
|||
return (x >> 6 | x << 26) ^ (x >> 11 | x << 21) ^ (x >> 25 | x << 7); |
|||
} |
|||
static uint32_t sigma0(uint32_t x) |
|||
{ |
|||
return (x >> 7 | x << 25) ^ (x >> 18 | x << 14) ^ (x >> 3); |
|||
} |
|||
static uint32_t sigma1(uint32_t x) |
|||
{ |
|||
return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10); |
|||
} |
|||
|
|||
/** One round of SHA-256. */ |
|||
static void Round(uint32_t a, uint32_t b, uint32_t c, uint32_t *d, uint32_t e, uint32_t f, uint32_t g, uint32_t *h, uint32_t k, uint32_t w) |
|||
{ |
|||
uint32_t t1 = *h + Sigma1(e) + Ch(e, f, g) + k + w; |
|||
uint32_t t2 = Sigma0(a) + Maj(a, b, c); |
|||
*d += t1; |
|||
*h = t1 + t2; |
|||
} |
|||
|
|||
/** Perform one SHA-256 transformation, processing a 64-byte chunk. */ |
|||
static void Transform(uint32_t *s, const uint32_t *chunk) |
|||
{ |
|||
uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; |
|||
uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; |
|||
|
|||
Round(a, b, c, &d, e, f, g, &h, 0x428a2f98, w0 = be32_to_cpu(chunk[0])); |
|||
Round(h, a, b, &c, d, e, f, &g, 0x71374491, w1 = be32_to_cpu(chunk[1])); |
|||
Round(g, h, a, &b, c, d, e, &f, 0xb5c0fbcf, w2 = be32_to_cpu(chunk[2])); |
|||
Round(f, g, h, &a, b, c, d, &e, 0xe9b5dba5, w3 = be32_to_cpu(chunk[3])); |
|||
Round(e, f, g, &h, a, b, c, &d, 0x3956c25b, w4 = be32_to_cpu(chunk[4])); |
|||
Round(d, e, f, &g, h, a, b, &c, 0x59f111f1, w5 = be32_to_cpu(chunk[5])); |
|||
Round(c, d, e, &f, g, h, a, &b, 0x923f82a4, w6 = be32_to_cpu(chunk[6])); |
|||
Round(b, c, d, &e, f, g, h, &a, 0xab1c5ed5, w7 = be32_to_cpu(chunk[7])); |
|||
Round(a, b, c, &d, e, f, g, &h, 0xd807aa98, w8 = be32_to_cpu(chunk[8])); |
|||
Round(h, a, b, &c, d, e, f, &g, 0x12835b01, w9 = be32_to_cpu(chunk[9])); |
|||
Round(g, h, a, &b, c, d, e, &f, 0x243185be, w10 = be32_to_cpu(chunk[10])); |
|||
Round(f, g, h, &a, b, c, d, &e, 0x550c7dc3, w11 = be32_to_cpu(chunk[11])); |
|||
Round(e, f, g, &h, a, b, c, &d, 0x72be5d74, w12 = be32_to_cpu(chunk[12])); |
|||
Round(d, e, f, &g, h, a, b, &c, 0x80deb1fe, w13 = be32_to_cpu(chunk[13])); |
|||
Round(c, d, e, &f, g, h, a, &b, 0x9bdc06a7, w14 = be32_to_cpu(chunk[14])); |
|||
Round(b, c, d, &e, f, g, h, &a, 0xc19bf174, w15 = be32_to_cpu(chunk[15])); |
|||
|
|||
Round(a, b, c, &d, e, f, g, &h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1)); |
|||
Round(h, a, b, &c, d, e, f, &g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2)); |
|||
Round(g, h, a, &b, c, d, e, &f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3)); |
|||
Round(f, g, h, &a, b, c, d, &e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4)); |
|||
Round(e, f, g, &h, a, b, c, &d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5)); |
|||
Round(d, e, f, &g, h, a, b, &c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6)); |
|||
Round(c, d, e, &f, g, h, a, &b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7)); |
|||
Round(b, c, d, &e, f, g, h, &a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8)); |
|||
Round(a, b, c, &d, e, f, g, &h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9)); |
|||
Round(h, a, b, &c, d, e, f, &g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10)); |
|||
Round(g, h, a, &b, c, d, e, &f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11)); |
|||
Round(f, g, h, &a, b, c, d, &e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12)); |
|||
Round(e, f, g, &h, a, b, c, &d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13)); |
|||
Round(d, e, f, &g, h, a, b, &c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14)); |
|||
Round(c, d, e, &f, g, h, a, &b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15)); |
|||
Round(b, c, d, &e, f, g, h, &a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0)); |
|||
|
|||
Round(a, b, c, &d, e, f, g, &h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1)); |
|||
Round(h, a, b, &c, d, e, f, &g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2)); |
|||
Round(g, h, a, &b, c, d, e, &f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3)); |
|||
Round(f, g, h, &a, b, c, d, &e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4)); |
|||
Round(e, f, g, &h, a, b, c, &d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5)); |
|||
Round(d, e, f, &g, h, a, b, &c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6)); |
|||
Round(c, d, e, &f, g, h, a, &b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7)); |
|||
Round(b, c, d, &e, f, g, h, &a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8)); |
|||
Round(a, b, c, &d, e, f, g, &h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9)); |
|||
Round(h, a, b, &c, d, e, f, &g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10)); |
|||
Round(g, h, a, &b, c, d, e, &f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11)); |
|||
Round(f, g, h, &a, b, c, d, &e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12)); |
|||
Round(e, f, g, &h, a, b, c, &d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13)); |
|||
Round(d, e, f, &g, h, a, b, &c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14)); |
|||
Round(c, d, e, &f, g, h, a, &b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15)); |
|||
Round(b, c, d, &e, f, g, h, &a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0)); |
|||
|
|||
Round(a, b, c, &d, e, f, g, &h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1)); |
|||
Round(h, a, b, &c, d, e, f, &g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2)); |
|||
Round(g, h, a, &b, c, d, e, &f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3)); |
|||
Round(f, g, h, &a, b, c, d, &e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4)); |
|||
Round(e, f, g, &h, a, b, c, &d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5)); |
|||
Round(d, e, f, &g, h, a, b, &c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6)); |
|||
Round(c, d, e, &f, g, h, a, &b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7)); |
|||
Round(b, c, d, &e, f, g, h, &a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8)); |
|||
Round(a, b, c, &d, e, f, g, &h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9)); |
|||
Round(h, a, b, &c, d, e, f, &g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10)); |
|||
Round(g, h, a, &b, c, d, e, &f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11)); |
|||
Round(f, g, h, &a, b, c, d, &e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12)); |
|||
Round(e, f, g, &h, a, b, c, &d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13)); |
|||
Round(d, e, f, &g, h, a, b, &c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14)); |
|||
Round(c, d, e, &f, g, h, a, &b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15)); |
|||
Round(b, c, d, &e, f, g, h, &a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0)); |
|||
|
|||
s[0] += a; |
|||
s[1] += b; |
|||
s[2] += c; |
|||
s[3] += d; |
|||
s[4] += e; |
|||
s[5] += f; |
|||
s[6] += g; |
|||
s[7] += h; |
|||
} |
|||
|
|||
static bool alignment_ok(const void *p UNUSED, size_t n UNUSED) |
|||
{ |
|||
#if HAVE_UNALIGNED_ACCESS |
|||
return true; |
|||
#else |
|||
return ((size_t)p % n == 0); |
|||
#endif |
|||
} |
|||
|
|||
static void add(struct sha256_ctx *ctx, const void *p, size_t len) |
|||
{ |
|||
const unsigned char *data = p; |
|||
size_t bufsize = ctx->bytes % 64; |
|||
|
|||
if (bufsize + len >= 64) { |
|||
/* Fill the buffer, and process it. */ |
|||
memcpy(ctx->buf.u8 + bufsize, data, 64 - bufsize); |
|||
ctx->bytes += 64 - bufsize; |
|||
data += 64 - bufsize; |
|||
len -= 64 - bufsize; |
|||
Transform(ctx->s, ctx->buf.u32); |
|||
bufsize = 0; |
|||
} |
|||
|
|||
while (len >= 64) { |
|||
/* Process full chunks directly from the source. */ |
|||
if (alignment_ok(data, sizeof(uint32_t))) |
|||
Transform(ctx->s, (const uint32_t *)data); |
|||
else { |
|||
memcpy(ctx->buf.u8, data, sizeof(ctx->buf)); |
|||
Transform(ctx->s, ctx->buf.u32); |
|||
} |
|||
ctx->bytes += 64; |
|||
data += 64; |
|||
len -= 64; |
|||
} |
|||
|
|||
if (len) { |
|||
/* Fill the buffer with what remains. */ |
|||
memcpy(ctx->buf.u8 + bufsize, data, len); |
|||
ctx->bytes += len; |
|||
} |
|||
} |
|||
|
|||
void sha256_init(struct sha256_ctx *ctx) |
|||
{ |
|||
struct sha256_ctx init = SHA256_INIT; |
|||
*ctx = init; |
|||
} |
|||
|
|||
void sha256_update(struct sha256_ctx *ctx, const void *p, size_t size) |
|||
{ |
|||
check_sha256(ctx); |
|||
add(ctx, p, size); |
|||
} |
|||
|
|||
void sha256_done(struct sha256_ctx *ctx, struct sha256 *res) |
|||
{ |
|||
static const unsigned char pad[64] = {0x80}; |
|||
uint64_t sizedesc; |
|||
size_t i; |
|||
|
|||
sizedesc = cpu_to_be64((uint64_t)ctx->bytes << 3); |
|||
/* Add '1' bit to terminate, then all 0 bits, up to next block - 8. */ |
|||
add(ctx, pad, 1 + ((128 - 8 - (ctx->bytes % 64) - 1) % 64)); |
|||
/* Add number of bits of data (big endian) */ |
|||
add(ctx, &sizedesc, 8); |
|||
for (i = 0; i < sizeof(ctx->s) / sizeof(ctx->s[0]); i++) |
|||
res->u.u32[i] = cpu_to_be32(ctx->s[i]); |
|||
invalidate_sha256(ctx); |
|||
} |
|||
#endif |
|||
|
|||
void sha256(struct sha256 *sha, const void *p, size_t size) |
|||
{ |
|||
struct sha256_ctx ctx; |
|||
|
|||
sha256_init(&ctx); |
|||
sha256_update(&ctx, p, size); |
|||
sha256_done(&ctx, sha); |
|||
} |
|||
|
|||
void sha256_u8(struct sha256_ctx *ctx, uint8_t v) |
|||
{ |
|||
sha256_update(ctx, &v, sizeof(v)); |
|||
} |
|||
|
|||
void sha256_u16(struct sha256_ctx *ctx, uint16_t v) |
|||
{ |
|||
sha256_update(ctx, &v, sizeof(v)); |
|||
} |
|||
|
|||
void sha256_u32(struct sha256_ctx *ctx, uint32_t v) |
|||
{ |
|||
sha256_update(ctx, &v, sizeof(v)); |
|||
} |
|||
|
|||
void sha256_u64(struct sha256_ctx *ctx, uint64_t v) |
|||
{ |
|||
sha256_update(ctx, &v, sizeof(v)); |
|||
} |
|||
|
|||
/* Add as little-endian */ |
|||
void sha256_le16(struct sha256_ctx *ctx, uint16_t v) |
|||
{ |
|||
leint16_t lev = cpu_to_le16(v); |
|||
sha256_update(ctx, &lev, sizeof(lev)); |
|||
} |
|||
|
|||
void sha256_le32(struct sha256_ctx *ctx, uint32_t v) |
|||
{ |
|||
leint32_t lev = cpu_to_le32(v); |
|||
sha256_update(ctx, &lev, sizeof(lev)); |
|||
} |
|||
|
|||
void sha256_le64(struct sha256_ctx *ctx, uint64_t v) |
|||
{ |
|||
leint64_t lev = cpu_to_le64(v); |
|||
sha256_update(ctx, &lev, sizeof(lev)); |
|||
} |
|||
|
|||
/* Add as big-endian */ |
|||
void sha256_be16(struct sha256_ctx *ctx, uint16_t v) |
|||
{ |
|||
beint16_t bev = cpu_to_be16(v); |
|||
sha256_update(ctx, &bev, sizeof(bev)); |
|||
} |
|||
|
|||
void sha256_be32(struct sha256_ctx *ctx, uint32_t v) |
|||
{ |
|||
beint32_t bev = cpu_to_be32(v); |
|||
sha256_update(ctx, &bev, sizeof(bev)); |
|||
} |
|||
|
|||
void sha256_be64(struct sha256_ctx *ctx, uint64_t v) |
|||
{ |
|||
beint64_t bev = cpu_to_be64(v); |
|||
sha256_update(ctx, &bev, sizeof(bev)); |
|||
} |
@ -0,0 +1,147 @@ |
|||
#ifndef CCAN_CRYPTO_SHA256_H |
|||
#define CCAN_CRYPTO_SHA256_H |
|||
/* BSD-MIT - see LICENSE file for details */ |
|||
#include "config.h" |
|||
#include <stdint.h> |
|||
#include <stdlib.h> |
|||
|
|||
/* Uncomment this to use openssl's SHA256 routines (and link with -lcrypto) */ |
|||
/*#define CCAN_CRYPTO_SHA256_USE_OPENSSL 1*/ |
|||
|
|||
#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL |
|||
#include <openssl/sha.h> |
|||
#endif |
|||
|
|||
/**
|
|||
* struct sha256 - structure representing a completed SHA256. |
|||
* @u.u8: an unsigned char array. |
|||
* @u.u32: a 32-bit integer array. |
|||
* |
|||
* Other fields may be added to the union in future. |
|||
*/ |
|||
struct sha256 { |
|||
union { |
|||
uint32_t u32[8]; |
|||
unsigned char u8[32]; |
|||
} u; |
|||
}; |
|||
|
|||
/**
|
|||
* sha256 - return sha256 of an object. |
|||
* @sha256: the sha256 to fill in |
|||
* @p: pointer to memory, |
|||
* @size: the number of bytes pointed to by |
|||
* |
|||
* The bytes pointed to by @p is SHA256 hashed into @sha256. This is |
|||
* equivalent to sha256_init(), sha256_update() then sha256_done(). |
|||
*/ |
|||
void sha256(struct sha256 *sha, const void *p, size_t size); |
|||
|
|||
/**
|
|||
* struct sha256_ctx - structure to store running context for sha256 |
|||
*/ |
|||
struct sha256_ctx { |
|||
#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL |
|||
SHA256_CTX c; |
|||
#else |
|||
uint32_t s[8]; |
|||
union { |
|||
uint32_t u32[16]; |
|||
unsigned char u8[64]; |
|||
} buf; |
|||
size_t bytes; |
|||
#endif |
|||
}; |
|||
|
|||
/**
|
|||
* sha256_init - initialize an SHA256 context. |
|||
* @ctx: the sha256_ctx to initialize |
|||
* |
|||
* This must be called before sha256_update or sha256_done, or |
|||
* alternately you can assign SHA256_INIT. |
|||
* |
|||
* If it was already initialized, this forgets anything which was |
|||
* hashed before. |
|||
* |
|||
* Example: |
|||
* static void hash_all(const char **arr, struct sha256 *hash) |
|||
* { |
|||
* size_t i; |
|||
* struct sha256_ctx ctx; |
|||
* |
|||
* sha256_init(&ctx); |
|||
* for (i = 0; arr[i]; i++) |
|||
* sha256_update(&ctx, arr[i], strlen(arr[i])); |
|||
* sha256_done(&ctx, hash); |
|||
* } |
|||
*/ |
|||
void sha256_init(struct sha256_ctx *ctx); |
|||
|
|||
/**
|
|||
* SHA256_INIT - initializer for an SHA256 context. |
|||
* |
|||
* This can be used to statically initialize an SHA256 context (instead |
|||
* of sha256_init()). |
|||
* |
|||
* Example: |
|||
* static void hash_all(const char **arr, struct sha256 *hash) |
|||
* { |
|||
* size_t i; |
|||
* struct sha256_ctx ctx = SHA256_INIT; |
|||
* |
|||
* for (i = 0; arr[i]; i++) |
|||
* sha256_update(&ctx, arr[i], strlen(arr[i])); |
|||
* sha256_done(&ctx, hash); |
|||
* } |
|||
*/ |
|||
#ifdef CCAN_CRYPTO_SHA256_USE_OPENSSL |
|||
#define SHA256_INIT \ |
|||
{ { { 0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, \ |
|||
0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul }, \ |
|||
0x0, 0x0, \ |
|||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, \ |
|||
0x0, 0x20 } } |
|||
#else |
|||
#define SHA256_INIT \ |
|||
{ { 0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, \ |
|||
0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul }, \ |
|||
{ { 0 } }, 0 } |
|||
#endif |
|||
|
|||
/**
|
|||
* sha256_update - include some memory in the hash. |
|||
* @ctx: the sha256_ctx to use |
|||
* @p: pointer to memory, |
|||
* @size: the number of bytes pointed to by |
|||
* |
|||
* You can call this multiple times to hash more data, before calling |
|||
* sha256_done(). |
|||
*/ |
|||
void sha256_update(struct sha256_ctx *ctx, const void *p, size_t size); |
|||
|
|||
/**
|
|||
* sha256_done - finish SHA256 and return the hash |
|||
* @ctx: the sha256_ctx to complete |
|||
* @res: the hash to return. |
|||
* |
|||
* Note that @ctx is *destroyed* by this, and must be reinitialized. |
|||
* To avoid that, pass a copy instead. |
|||
*/ |
|||
void sha256_done(struct sha256_ctx *sha256, struct sha256 *res); |
|||
|
|||
/* Add various types to an SHA256 hash */ |
|||
void sha256_u8(struct sha256_ctx *ctx, uint8_t v); |
|||
void sha256_u16(struct sha256_ctx *ctx, uint16_t v); |
|||
void sha256_u32(struct sha256_ctx *ctx, uint32_t v); |
|||
void sha256_u64(struct sha256_ctx *ctx, uint64_t v); |
|||
|
|||
/* Add as little-endian */ |
|||
void sha256_le16(struct sha256_ctx *ctx, uint16_t v); |
|||
void sha256_le32(struct sha256_ctx *ctx, uint32_t v); |
|||
void sha256_le64(struct sha256_ctx *ctx, uint64_t v); |
|||
|
|||
/* Add as big-endian */ |
|||
void sha256_be16(struct sha256_ctx *ctx, uint16_t v); |
|||
void sha256_be32(struct sha256_ctx *ctx, uint32_t v); |
|||
void sha256_be64(struct sha256_ctx *ctx, uint64_t v); |
|||
#endif /* CCAN_CRYPTO_SHA256_H */ |
@ -0,0 +1,35 @@ |
|||
/* CC0 (Public domain) - see LICENSE file for details */ |
|||
#ifndef CCAN_SHORT_TYPES_H |
|||
#define CCAN_SHORT_TYPES_H |
|||
#include <stdint.h> |
|||
|
|||
/**
|
|||
* u64/s64/u32/s32/u16/s16/u8/s8 - short names for explicitly-sized types. |
|||
*/ |
|||
typedef uint64_t u64; |
|||
typedef int64_t s64; |
|||
typedef uint32_t u32; |
|||
typedef int32_t s32; |
|||
typedef uint16_t u16; |
|||
typedef int16_t s16; |
|||
typedef uint8_t u8; |
|||
typedef int8_t s8; |
|||
|
|||
/* Whichever they include first, they get these definitions. */ |
|||
#ifdef CCAN_ENDIAN_H |
|||
/**
|
|||
* be64/be32/be16 - 64/32/16 bit big-endian representation. |
|||
*/ |
|||
typedef beint64_t be64; |
|||
typedef beint32_t be32; |
|||
typedef beint16_t be16; |
|||
|
|||
/**
|
|||
* le64/le32/le16 - 64/32/16 bit little-endian representation. |
|||
*/ |
|||
typedef leint64_t le64; |
|||
typedef leint32_t le32; |
|||
typedef leint16_t le16; |
|||
#endif |
|||
|
|||
#endif /* CCAN_SHORT_TYPES_H */ |
@ -0,0 +1,228 @@ |
|||
/* CC0 (Public domain) - see LICENSE file for details */ |
|||
#ifndef CCAN_STR_H |
|||
#define CCAN_STR_H |
|||
#include "config.h" |
|||
#include <string.h> |
|||
#include <stdbool.h> |
|||
#include <limits.h> |
|||
#include <ctype.h> |
|||
|
|||
/**
|
|||
* streq - Are two strings equal? |
|||
* @a: first string |
|||
* @b: first string |
|||
* |
|||
* This macro is arguably more readable than "!strcmp(a, b)". |
|||
* |
|||
* Example: |
|||
* if (streq(somestring, "")) |
|||
* printf("String is empty!\n"); |
|||
*/ |
|||
#define streq(a,b) (strcmp((a),(b)) == 0) |
|||
|
|||
/**
|
|||
* strstarts - Does this string start with this prefix? |
|||
* @str: string to test |
|||
* @prefix: prefix to look for at start of str |
|||
* |
|||
* Example: |
|||
* if (strstarts(somestring, "foo")) |
|||
* printf("String %s begins with 'foo'!\n", somestring); |
|||
*/ |
|||
#define strstarts(str,prefix) (strncmp((str),(prefix),strlen(prefix)) == 0) |
|||
|
|||
/**
|
|||
* strends - Does this string end with this postfix? |
|||
* @str: string to test |
|||
* @postfix: postfix to look for at end of str |
|||
* |
|||
* Example: |
|||
* if (strends(somestring, "foo")) |
|||
* printf("String %s end with 'foo'!\n", somestring); |
|||
*/ |
|||
static inline bool strends(const char *str, const char *postfix) |
|||
{ |
|||
if (strlen(str) < strlen(postfix)) |
|||
return false; |
|||
|
|||
return streq(str + strlen(str) - strlen(postfix), postfix); |
|||
} |
|||
|
|||
/**
|
|||
* stringify - Turn expression into a string literal |
|||
* @expr: any C expression |
|||
* |
|||
* Example: |
|||
* #define PRINT_COND_IF_FALSE(cond) \ |
|||
* ((cond) || printf("%s is false!", stringify(cond))) |
|||
*/ |
|||
#define stringify(expr) stringify_1(expr) |
|||
/* Double-indirection required to stringify expansions */ |
|||
#define stringify_1(expr) #expr |
|||
|
|||
/**
|
|||
* strcount - Count number of (non-overlapping) occurrences of a substring. |
|||
* @haystack: a C string |
|||
* @needle: a substring |
|||
* |
|||
* Example: |
|||
* assert(strcount("aaa aaa", "a") == 6); |
|||
* assert(strcount("aaa aaa", "ab") == 0); |
|||
* assert(strcount("aaa aaa", "aa") == 2); |
|||
*/ |
|||
size_t strcount(const char *haystack, const char *needle); |
|||
|
|||
/**
|
|||
* STR_MAX_CHARS - Maximum possible size of numeric string for this type. |
|||
* @type_or_expr: a pointer or integer type or expression. |
|||
* |
|||
* This provides enough space for a nul-terminated string which represents the |
|||
* largest possible value for the type or expression. |
|||
* |
|||
* Note: The implementation adds extra space so hex values or negative |
|||
* values will fit (eg. sprintf(... "%p"). ) |
|||
* |
|||
* Example: |
|||
* char str[STR_MAX_CHARS(int)]; |
|||
* |
|||
* sprintf(str, "%i", 7); |
|||
*/ |
|||
#define STR_MAX_CHARS(type_or_expr) \ |
|||
((sizeof(type_or_expr) * CHAR_BIT + 8) / 9 * 3 + 2 \ |
|||
+ STR_MAX_CHARS_TCHECK_(type_or_expr)) |
|||
|
|||
#if HAVE_TYPEOF |
|||
/* Only a simple type can have 0 assigned, so test that. */ |
|||
#define STR_MAX_CHARS_TCHECK_(type_or_expr) \ |
|||
(sizeof(({ typeof(type_or_expr) x = 0; x; }))*0) |
|||
#else |
|||
#define STR_MAX_CHARS_TCHECK_(type_or_expr) 0 |
|||
#endif |
|||
|
|||
/**
|
|||
* cisalnum - isalnum() which takes a char (and doesn't accept EOF) |
|||
* @c: a character |
|||
* |
|||
* Surprisingly, the standard ctype.h isalnum() takes an int, which |
|||
* must have the value of EOF (-1) or an unsigned char. This variant |
|||
* takes a real char, and doesn't accept EOF. |
|||
*/ |
|||
static inline bool cisalnum(char c) |
|||
{ |
|||
return isalnum((unsigned char)c); |
|||
} |
|||
static inline bool cisalpha(char c) |
|||
{ |
|||
return isalpha((unsigned char)c); |
|||
} |
|||
static inline bool cisascii(char c) |
|||
{ |
|||
return isascii((unsigned char)c); |
|||
} |
|||
#if HAVE_ISBLANK |
|||
static inline bool cisblank(char c) |
|||
{ |
|||
return isblank((unsigned char)c); |
|||
} |
|||
#endif |
|||
static inline bool ciscntrl(char c) |
|||
{ |
|||
return iscntrl((unsigned char)c); |
|||
} |
|||
static inline bool cisdigit(char c) |
|||
{ |
|||
return isdigit((unsigned char)c); |
|||
} |
|||
static inline bool cisgraph(char c) |
|||
{ |
|||
return isgraph((unsigned char)c); |
|||
} |
|||
static inline bool cislower(char c) |
|||
{ |
|||
return islower((unsigned char)c); |
|||
} |
|||
static inline bool cisprint(char c) |
|||
{ |
|||
return isprint((unsigned char)c); |
|||
} |
|||
static inline bool cispunct(char c) |
|||
{ |
|||
return ispunct((unsigned char)c); |
|||
} |
|||
static inline bool cisspace(char c) |
|||
{ |
|||
return isspace((unsigned char)c); |
|||
} |
|||
static inline bool cisupper(char c) |
|||
{ |
|||
return isupper((unsigned char)c); |
|||
} |
|||
static inline bool cisxdigit(char c) |
|||
{ |
|||
return isxdigit((unsigned char)c); |
|||
} |
|||
|
|||
#include "str_debug.h" |
|||
|
|||
/* These checks force things out of line, hence they are under DEBUG. */ |
|||
#ifdef CCAN_STR_DEBUG |
|||
#include <ccan/build_assert/build_assert.h> |
|||
|
|||
/* These are commonly misused: they take -1 or an *unsigned* char value. */ |
|||
#undef isalnum |
|||
#undef isalpha |
|||
#undef isascii |
|||
#undef isblank |
|||
#undef iscntrl |
|||
#undef isdigit |
|||
#undef isgraph |
|||
#undef islower |
|||
#undef isprint |
|||
#undef ispunct |
|||
#undef isspace |
|||
#undef isupper |
|||
#undef isxdigit |
|||
|
|||
/* You can use a char if char is unsigned. */ |
|||
#if HAVE_BUILTIN_TYPES_COMPATIBLE_P && HAVE_TYPEOF |
|||
#define str_check_arg_(i) \ |
|||
((i) + BUILD_ASSERT_OR_ZERO(!__builtin_types_compatible_p(typeof(i), \ |
|||
char) \ |
|||
|| (char)255 > 0)) |
|||
#else |
|||
#define str_check_arg_(i) (i) |
|||
#endif |
|||
|
|||
#define isalnum(i) str_isalnum(str_check_arg_(i)) |
|||
#define isalpha(i) str_isalpha(str_check_arg_(i)) |
|||
#define isascii(i) str_isascii(str_check_arg_(i)) |
|||
#if HAVE_ISBLANK |
|||
#define isblank(i) str_isblank(str_check_arg_(i)) |
|||
#endif |
|||
#define iscntrl(i) str_iscntrl(str_check_arg_(i)) |
|||
#define isdigit(i) str_isdigit(str_check_arg_(i)) |
|||
#define isgraph(i) str_isgraph(str_check_arg_(i)) |
|||
#define islower(i) str_islower(str_check_arg_(i)) |
|||
#define isprint(i) str_isprint(str_check_arg_(i)) |
|||
#define ispunct(i) str_ispunct(str_check_arg_(i)) |
|||
#define isspace(i) str_isspace(str_check_arg_(i)) |
|||
#define isupper(i) str_isupper(str_check_arg_(i)) |
|||
#define isxdigit(i) str_isxdigit(str_check_arg_(i)) |
|||
|
|||
#if HAVE_TYPEOF |
|||
/* With GNU magic, we can make const-respecting standard string functions. */ |
|||
#undef strstr |
|||
#undef strchr |
|||
#undef strrchr |
|||
|
|||
/* + 0 is needed to decay array into pointer. */ |
|||
#define strstr(haystack, needle) \ |
|||
((typeof((haystack) + 0))str_strstr((haystack), (needle))) |
|||
#define strchr(haystack, c) \ |
|||
((typeof((haystack) + 0))str_strchr((haystack), (c))) |
|||
#define strrchr(haystack, c) \ |
|||
((typeof((haystack) + 0))str_strrchr((haystack), (c))) |
|||
#endif |
|||
#endif /* CCAN_STR_DEBUG */ |
|||
|
|||
#endif /* CCAN_STR_H */ |
@ -0,0 +1,30 @@ |
|||
/* CC0 (Public domain) - see LICENSE file for details */ |
|||
#ifndef CCAN_STR_DEBUG_H |
|||
#define CCAN_STR_DEBUG_H |
|||
|
|||
/* #define CCAN_STR_DEBUG 1 */ |
|||
|
|||
#ifdef CCAN_STR_DEBUG |
|||
/* Because we mug the real ones with macros, we need our own wrappers. */ |
|||
int str_isalnum(int i); |
|||
int str_isalpha(int i); |
|||
int str_isascii(int i); |
|||
#if HAVE_ISBLANK |
|||
int str_isblank(int i); |
|||
#endif |
|||
int str_iscntrl(int i); |
|||
int str_isdigit(int i); |
|||
int str_isgraph(int i); |
|||
int str_islower(int i); |
|||
int str_isprint(int i); |
|||
int str_ispunct(int i); |
|||
int str_isspace(int i); |
|||
int str_isupper(int i); |
|||
int str_isxdigit(int i); |
|||
|
|||
char *str_strstr(const char *haystack, const char *needle); |
|||
char *str_strchr(const char *s, int c); |
|||
char *str_strrchr(const char *s, int c); |
|||
#endif /* CCAN_STR_DEBUG */ |
|||
|
|||
#endif /* CCAN_STR_DEBUG_H */ |
@ -0,0 +1,46 @@ |
|||
/* MIT (BSD) license - see LICENSE file for details */ |
|||
#ifndef CCAN_STRUCTEQ_H |
|||
#define CCAN_STRUCTEQ_H |
|||
#include "build_assert.h" |
|||
#include "cppmagic.h" |
|||
#include <string.h> |
|||
#include <stdbool.h> |
|||
|
|||
/**
|
|||
* STRUCTEQ_DEF - define an ..._eq function to compare two structures. |
|||
* @sname: name of the structure, and function (<sname>_eq) to define. |
|||
* @padbytes: number of bytes of expected padding, or negative "max". |
|||
* @...: name of every member of the structure. |
|||
* |
|||
* This generates a single memcmp() call in the common case where the |
|||
* structure contains no padding. Since it can't tell the difference between |
|||
* padding and a missing member, @padbytes can be used to assert that |
|||
* there isn't any, or how many we expect. A negative number means |
|||
* "up to or equal to that amount of padding", as padding can be |
|||
* platform dependent. |
|||
*/ |
|||
#define STRUCTEQ_DEF(sname, padbytes, ...) \ |
|||
static inline bool CPPMAGIC_GLUE2(sname, _eq)(const struct sname *_a, \ |
|||
const struct sname *_b) \ |
|||
{ \ |
|||
BUILD_ASSERT(((padbytes) < 0 && \ |
|||
CPPMAGIC_JOIN(+, CPPMAGIC_MAP(STRUCTEQ_MEMBER_SIZE_, \ |
|||
__VA_ARGS__)) \ |
|||
- (padbytes) >= sizeof(*_a)) \ |
|||
|| CPPMAGIC_JOIN(+, CPPMAGIC_MAP(STRUCTEQ_MEMBER_SIZE_, \ |
|||
__VA_ARGS__)) \ |
|||
+ (padbytes) == sizeof(*_a)); \ |
|||
if (CPPMAGIC_JOIN(+, CPPMAGIC_MAP(STRUCTEQ_MEMBER_SIZE_, __VA_ARGS__)) \ |
|||
== sizeof(*_a)) \ |
|||
return memcmp(_a, _b, sizeof(*_a)) == 0; \ |
|||
else \ |
|||
return CPPMAGIC_JOIN(&&, \ |
|||
CPPMAGIC_MAP(STRUCTEQ_MEMBER_CMP_, \ |
|||
__VA_ARGS__)); \ |
|||
} |
|||
|
|||
/* Helpers */ |
|||
#define STRUCTEQ_MEMBER_SIZE_(m) sizeof((_a)->m) |
|||
#define STRUCTEQ_MEMBER_CMP_(m) memcmp(&_a->m, &_b->m, sizeof(_a->m)) == 0 |
|||
|
|||
#endif /* CCAN_STRUCTEQ_H */ |
@ -0,0 +1,126 @@ |
|||
/* CC0 (Public domain) - see LICENSE file for details */ |
|||
#include "take.h" |
|||
#include "likely.h" |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
|
|||
static const void **takenarr; |
|||
static const char **labelarr; |
|||
static size_t max_taken, num_taken; |
|||
static size_t allocfail; |
|||
static void (*allocfailfn)(const void *p); |
|||
|
|||
void *take_(const void *p, const char *label) |
|||
{ |
|||
/* Overallocate: it's better than risking calloc returning NULL! */ |
|||
if (unlikely(label && !labelarr)) |
|||
labelarr = calloc(max_taken+1, sizeof(*labelarr)); |
|||
|
|||
if (unlikely(num_taken == max_taken)) { |
|||
const void **new; |
|||
|
|||
new = realloc(takenarr, sizeof(*takenarr) * (max_taken+1)); |
|||
if (unlikely(!new)) { |
|||
if (allocfailfn) { |
|||
allocfail++; |
|||
allocfailfn(p); |
|||
return NULL; |
|||
} |
|||
/* Otherwise we leak p. */ |
|||
return (void *)p; |
|||
} |
|||
takenarr = new; |
|||
/* Once labelarr is set, we maintain it. */ |
|||
if (labelarr) { |
|||
const char **labelarr_new; |
|||
labelarr_new = realloc(labelarr, |
|||
sizeof(*labelarr) * (max_taken+1)); |
|||
if (labelarr_new) { |
|||
labelarr = labelarr_new; |
|||
} else { |
|||
/* num_taken will be out of sync with the size of
|
|||
* labelarr after realloc failure. |
|||
* Just pretend that we never had labelarr allocated. */ |
|||
free(labelarr); |
|||
labelarr = NULL; |
|||
} |
|||
} |
|||
max_taken++; |
|||
} |
|||
if (unlikely(labelarr)) |
|||
labelarr[num_taken] = label; |
|||
takenarr[num_taken++] = p; |
|||
|
|||
return (void *)p; |
|||
} |
|||
|
|||
static size_t find_taken(const void *p) |
|||
{ |
|||
size_t i; |
|||
|
|||
for (i = 0; i < num_taken; i++) { |
|||
if (takenarr[i] == p) |
|||
return i+1; |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
bool taken(const void *p) |
|||
{ |
|||
size_t i; |
|||
|
|||
if (!p && unlikely(allocfail)) { |
|||
allocfail--; |
|||
return true; |
|||
} |
|||
|
|||
i = find_taken(p); |
|||
if (!i) |
|||
return false; |
|||
|
|||
memmove(&takenarr[i-1], &takenarr[i], |
|||
(--num_taken - (i - 1))*sizeof(takenarr[0])); |
|||
return true; |
|||
} |
|||
|
|||
bool is_taken(const void *p) |
|||
{ |
|||
if (!p && unlikely(allocfail)) |
|||
return true; |
|||
|
|||
return find_taken(p) > 0; |
|||
} |
|||
|
|||
const char *taken_any(void) |
|||
{ |
|||
static char pointer_buf[32]; |
|||
|
|||
if (num_taken == 0) |
|||
return NULL; |
|||
|
|||
/* We're *allowed* to have some with labels, some without. */ |
|||
if (labelarr) { |
|||
size_t i; |
|||
for (i = 0; i < num_taken; i++) |
|||
if (labelarr[i]) |
|||
return labelarr[i]; |
|||
} |
|||
|
|||
sprintf(pointer_buf, "%p", takenarr[0]); |
|||
return pointer_buf; |
|||
} |
|||
|
|||
void take_cleanup(void) |
|||
{ |
|||
max_taken = num_taken = 0; |
|||
free(takenarr); |
|||
takenarr = NULL; |
|||
free(labelarr); |
|||
labelarr = NULL; |
|||
} |
|||
|
|||
void take_allocfail(void (*fn)(const void *p)) |
|||
{ |
|||
allocfailfn = fn; |
|||
} |
@ -0,0 +1,136 @@ |
|||
/* CC0 (Public domain) - see LICENSE file for details */ |
|||
#ifndef CCAN_TAKE_H |
|||
#define CCAN_TAKE_H |
|||
#include "config.h" |
|||
#include <stdbool.h> |
|||
#include "str.h" |
|||
|
|||
#ifdef CCAN_TAKE_DEBUG |
|||
#define TAKE_LABEL(p) __FILE__ ":" stringify(__LINE__) ":" stringify(p) |
|||
#else |
|||
#define TAKE_LABEL(p) NULL |
|||
#endif |
|||
|
|||
/**
|
|||
* TAKES - annotate a formal parameter as being take()-able |
|||
* |
|||
* This doesn't do anything, but useful for documentation. |
|||
* |
|||
* Example: |
|||
* void print_string(const char *str TAKES); |
|||
* |
|||
*/ |
|||
#define TAKES |
|||
|
|||
/**
|
|||
* take - record a pointer to be consumed by the function its handed to. |
|||
* @p: the pointer to mark, or NULL. |
|||
* |
|||
* This marks a pointer object to be freed by the called function, |
|||
* which is extremely useful for chaining functions. It works on |
|||
* NULL, for pass-through error handling. |
|||
*/ |
|||
#define take(p) (take_typeof(p) take_((p), TAKE_LABEL(p))) |
|||
|
|||
/**
|
|||
* taken - check (and un-take) a pointer was passed with take() |
|||
* @p: the pointer to check. |
|||
* |
|||
* A function which accepts take() arguments uses this to see if it |
|||
* should own the pointer; it will be removed from the take list, so |
|||
* this only returns true once. |
|||
* |
|||
* Example: |
|||
* // Silly routine to add 1
|
|||
* static int *add_one(const int *num TAKES) |
|||
* { |
|||
* int *ret; |
|||
* if (taken(num)) |
|||
* ret = (int *)num; |
|||
* else |
|||
* ret = malloc(sizeof(int)); |
|||
* if (ret) |
|||
* *ret = (*num) + 1; |
|||
* return ret; |
|||
* } |
|||
*/ |
|||
bool taken(const void *p); |
|||
|
|||
/**
|
|||
* is_taken - check if a pointer was passed with take() |
|||
* @p: the pointer to check. |
|||
* |
|||
* This is like the above, but doesn't remove it from the taken list. |
|||
* |
|||
* Example: |
|||
* // Silly routine to add 1: doesn't handle taken args!
|
|||
* static int *add_one_notake(const int *num) |
|||
* { |
|||
* int *ret = malloc(sizeof(int)); |
|||
* assert(!is_taken(num)); |
|||
* if (ret) |
|||
* *ret = (*num) + 1; |
|||
* return ret; |
|||
* } |
|||
*/ |
|||
bool is_taken(const void *p); |
|||
|
|||
/**
|
|||
* taken_any - are there any taken pointers? |
|||
* |
|||
* Mainly useful for debugging take() leaks. With CCAN_TAKE_DEBUG, returns |
|||
* the label where the pointer was passed to take(), otherwise returns |
|||
* a static char buffer with the pointer value in it. NULL if none are taken. |
|||
* |
|||
* Example: |
|||
* static void cleanup(void) |
|||
* { |
|||
* assert(!taken_any()); |
|||
* } |
|||
*/ |
|||
const char *taken_any(void); |
|||
|
|||
/**
|
|||
* take_cleanup - remove all taken pointers from list. |
|||
* |
|||
* This is useful in atexit() handlers for valgrind-style leak detection. |
|||
* |
|||
* Example: |
|||
* static void cleanup2(void) |
|||
* { |
|||
* take_cleanup(); |
|||
* } |
|||
*/ |
|||
void take_cleanup(void); |
|||
|
|||
/**
|
|||
* take_allocfail - set function to call if we can't reallocated taken array. |
|||
* @fn: the function. |
|||
* |
|||
* If this is not set, then if the array reallocation fails, the |
|||
* pointer won't be marked taken(). If @fn returns, it is expected to |
|||
* free the pointer; we return NULL from take() and the function handles |
|||
* it like any allocation failure. |
|||
* |
|||
* Example: |
|||
* static void free_on_fail(const void *p) |
|||
* { |
|||
* free((void *)p); |
|||
* } |
|||
* |
|||
* static void init(void) |
|||
* { |
|||
* take_allocfail(free_on_fail); |
|||
* } |
|||
*/ |
|||
void take_allocfail(void (*fn)(const void *p)); |
|||
|
|||
/* Private functions */ |
|||
#if HAVE_TYPEOF |
|||
#define take_typeof(ptr) (__typeof__(ptr)) |
|||
#else |
|||
#define take_typeof(ptr) |
|||
#endif |
|||
|
|||
void *take_(const void *p, const char *label); |
|||
#endif /* CCAN_TAKE_H */ |
@ -0,0 +1,972 @@ |
|||
/* Licensed under BSD-MIT - see LICENSE file for details */ |
|||
#include "tal.h" |
|||
#include "compiler.h" |
|||
#include "list.h" |
|||
#include "alignof.h" |
|||
|
|||
#include <assert.h> |
|||
#include <stdio.h> |
|||
#include <stddef.h> |
|||
#include <string.h> |
|||
#include <limits.h> |
|||
#include <stdint.h> |
|||
#include <errno.h> |
|||
|
|||
//#define TAL_DEBUG 1
|
|||
|
|||
#define NOTIFY_IS_DESTRUCTOR 512 |
|||
#define NOTIFY_EXTRA_ARG 1024 |
|||
|
|||
/* This makes our parent_child ptr stand out for to_tal_hdr checks */ |
|||
#define TAL_PTR_OBFUSTICATOR ((intptr_t)0x1984200820142016ULL) |
|||
|
|||
/* 32-bit type field, first byte 0 in either endianness. */ |
|||
enum prop_type { |
|||
CHILDREN = 0x00c1d500, |
|||
NAME = 0x00111100, |
|||
NOTIFIER = 0x00071f00, |
|||
}; |
|||
|
|||
struct tal_hdr { |
|||
struct list_node list; |
|||
struct prop_hdr *prop; |
|||
/* XOR with TAL_PTR_OBFUSTICATOR */ |
|||
intptr_t parent_child; |
|||
size_t bytelen; |
|||
}; |
|||
|
|||
struct prop_hdr { |
|||
enum prop_type type; |
|||
struct prop_hdr *next; |
|||
}; |
|||
|
|||
struct children { |
|||
struct prop_hdr hdr; /* CHILDREN */ |
|||
struct tal_hdr *parent; |
|||
struct list_head children; /* Head of siblings. */ |
|||
}; |
|||
|
|||
struct name { |
|||
struct prop_hdr hdr; /* NAME */ |
|||
char name[]; |
|||
}; |
|||
|
|||
struct notifier { |
|||
struct prop_hdr hdr; /* NOTIFIER */ |
|||
enum tal_notify_type types; |
|||
union notifier_cb { |
|||
void (*notifyfn)(tal_t *, enum tal_notify_type, void *); |
|||
void (*destroy)(tal_t *); /* If NOTIFY_IS_DESTRUCTOR set */ |
|||
void (*destroy2)(tal_t *, void *); /* If NOTIFY_EXTRA_ARG */ |
|||
} u; |
|||
}; |
|||
|
|||
/* Extra arg */ |
|||
struct notifier_extra_arg { |
|||
struct notifier n; |
|||
void *arg; |
|||
}; |
|||
|
|||
#define EXTRA_ARG(n) (((struct notifier_extra_arg *)(n))->arg) |
|||
|
|||
static struct { |
|||
struct tal_hdr hdr; |
|||
struct children c; |
|||
} null_parent = { { { &null_parent.hdr.list, &null_parent.hdr.list }, |
|||
&null_parent.c.hdr, TAL_PTR_OBFUSTICATOR, 0 }, |
|||
{ { CHILDREN, NULL }, |
|||
&null_parent.hdr, |
|||
{ { &null_parent.c.children.n, |
|||
&null_parent.c.children.n } } |
|||
} |
|||
}; |
|||
|
|||
|
|||
static void *(*allocfn)(size_t size) = malloc; |
|||
static void *(*resizefn)(void *, size_t size) = realloc; |
|||
static void (*freefn)(void *) = free; |
|||
static void (*errorfn)(const char *msg) = (void *)abort; |
|||
/* Count on non-destrutor notifiers; often stays zero. */ |
|||
static size_t notifiers = 0; |
|||
|
|||
static inline void COLD call_error(const char *msg) |
|||
{ |
|||
errorfn(msg); |
|||
} |
|||
|
|||
static bool get_destroying_bit(intptr_t parent_child) |
|||
{ |
|||
return parent_child & 1; |
|||
} |
|||
|
|||
static void set_destroying_bit(intptr_t *parent_child) |
|||
{ |
|||
*parent_child |= 1; |
|||
} |
|||
|
|||
static struct children *ignore_destroying_bit(intptr_t parent_child) |
|||
{ |
|||
return (void *)((parent_child ^ TAL_PTR_OBFUSTICATOR) & ~(intptr_t)1); |
|||
} |
|||
|
|||
/* This means valgrind can see leaks. */ |
|||
void tal_cleanup(void) |
|||
{ |
|||
struct tal_hdr *i; |
|||
|
|||
while ((i = list_top(&null_parent.c.children, struct tal_hdr, list))) { |
|||
list_del(&i->list); |
|||
memset(i, 0, sizeof(*i)); |
|||
} |
|||
|
|||
/* Cleanup any taken pointers. */ |
|||
take_cleanup(); |
|||
} |
|||
|
|||
/* We carefully start all real properties with a zero byte. */ |
|||
static bool is_literal(const struct prop_hdr *prop) |
|||
{ |
|||
return ((char *)prop)[0] != 0; |
|||
} |
|||
|
|||
#ifndef NDEBUG |
|||
static const void *bounds_start, *bounds_end; |
|||
|
|||
static void update_bounds(const void *new, size_t size) |
|||
{ |
|||
if (unlikely(!bounds_start)) { |
|||
bounds_start = new; |
|||
bounds_end = (char *)new + size; |
|||
} else if (new < bounds_start) |
|||
bounds_start = new; |
|||
else if ((char *)new + size > (char *)bounds_end) |
|||
bounds_end = (char *)new + size; |
|||
} |
|||
|
|||
static bool in_bounds(const void *p) |
|||
{ |
|||
return !p |
|||
|| (p >= (void *)&null_parent && p <= (void *)(&null_parent + 1)) |
|||
|| (p >= bounds_start && p <= bounds_end); |
|||
} |
|||
#else |
|||
static void update_bounds(const void *new, size_t size) |
|||
{ |
|||
} |
|||
|
|||
static bool in_bounds(const void *p) |
|||
{ |
|||
return true; |
|||
} |
|||
#endif |
|||
|
|||
static void check_bounds(const void *p) |
|||
{ |
|||
if (!in_bounds(p)) |
|||
call_error("Not a valid header"); |
|||
} |
|||
|
|||
static struct tal_hdr *to_tal_hdr(const void *ctx) |
|||
{ |
|||
struct tal_hdr *t; |
|||
|
|||
t = (struct tal_hdr *)((char *)ctx - sizeof(struct tal_hdr)); |
|||
check_bounds(t); |
|||
check_bounds(ignore_destroying_bit(t->parent_child)); |
|||
check_bounds(t->list.next); |
|||
check_bounds(t->list.prev); |
|||
if (t->prop && !is_literal(t->prop)) |
|||
check_bounds(t->prop); |
|||
return t; |
|||
} |
|||
|
|||
static struct tal_hdr *to_tal_hdr_or_null(const void *ctx) |
|||
{ |
|||
if (!ctx) |
|||
return &null_parent.hdr; |
|||
return to_tal_hdr(ctx); |
|||
} |
|||
|
|||
static void *from_tal_hdr(const struct tal_hdr *hdr) |
|||
{ |
|||
return (void *)(hdr + 1); |
|||
} |
|||
|
|||
static void *from_tal_hdr_or_null(const struct tal_hdr *hdr) |
|||
{ |
|||
if (hdr == &null_parent.hdr) |
|||
return NULL; |
|||
return from_tal_hdr(hdr); |
|||
} |
|||
|
|||
#ifdef TAL_DEBUG |
|||
static struct tal_hdr *debug_tal(struct tal_hdr *tal) |
|||
{ |
|||
tal_check(from_tal_hdr_or_null(tal), "TAL_DEBUG "); |
|||
return tal; |
|||
} |
|||
#else |
|||
static struct tal_hdr *debug_tal(struct tal_hdr *tal) |
|||
{ |
|||
return tal; |
|||
} |
|||
#endif |
|||
|
|||
static void notify(const struct tal_hdr *ctx, |
|||
enum tal_notify_type type, const void *info, |
|||
int saved_errno) |
|||
{ |
|||
const struct prop_hdr *p; |
|||
|
|||
for (p = ctx->prop; p; p = p->next) { |
|||
struct notifier *n; |
|||
|
|||
if (is_literal(p)) |
|||
break; |
|||
if (p->type != NOTIFIER) |
|||
continue; |
|||
n = (struct notifier *)p; |
|||
if (n->types & type) { |
|||
errno = saved_errno; |
|||
if (n->types & NOTIFY_IS_DESTRUCTOR) { |
|||
/* Blatt this notifier in case it tries to
|
|||
* tal_del_destructor() from inside */ |
|||
union notifier_cb cb = n->u; |
|||
/* It's a union, so this NULLs destroy2 too! */ |
|||
n->u.destroy = NULL; |
|||
if (n->types & NOTIFY_EXTRA_ARG) |
|||
cb.destroy2(from_tal_hdr(ctx), |
|||
EXTRA_ARG(n)); |
|||
else |
|||
cb.destroy(from_tal_hdr(ctx)); |
|||
} else |
|||
n->u.notifyfn(from_tal_hdr_or_null(ctx), type, |
|||
(void *)info); |
|||
} |
|||
} |
|||
} |
|||
|
|||
static void *allocate(size_t size) |
|||
{ |
|||
void *ret = allocfn(size); |
|||
if (!ret) |
|||
call_error("allocation failed"); |
|||
else |
|||
update_bounds(ret, size); |
|||
return ret; |
|||
} |
|||
|
|||
static struct prop_hdr **find_property_ptr(const struct tal_hdr *t, |
|||
enum prop_type type) |
|||
{ |
|||
struct prop_hdr **p; |
|||
|
|||
for (p = (struct prop_hdr **)&t->prop; *p; p = &(*p)->next) { |
|||
if (is_literal(*p)) { |
|||
if (type == NAME) |
|||
return p; |
|||
break; |
|||
} |
|||
if ((*p)->type == type) |
|||
return p; |
|||
} |
|||
return NULL; |
|||
} |
|||
|
|||
static void *find_property(const struct tal_hdr *parent, enum prop_type type) |
|||
{ |
|||
struct prop_hdr **p = find_property_ptr(parent, type); |
|||
|
|||
if (p) |
|||
return *p; |
|||
return NULL; |
|||
} |
|||
|
|||
static void init_property(struct prop_hdr *hdr, |
|||
struct tal_hdr *parent, |
|||
enum prop_type type) |
|||
{ |
|||
hdr->type = type; |
|||
hdr->next = parent->prop; |
|||
parent->prop = hdr; |
|||
} |
|||
|
|||
static struct notifier *add_notifier_property(struct tal_hdr *t, |
|||
enum tal_notify_type types, |
|||
void (*fn)(void *, |
|||
enum tal_notify_type, |
|||
void *), |
|||
void *extra_arg) |
|||
{ |
|||
struct notifier *prop; |
|||
|
|||
if (types & NOTIFY_EXTRA_ARG) |
|||
prop = allocate(sizeof(struct notifier_extra_arg)); |
|||
else |
|||
prop = allocate(sizeof(struct notifier)); |
|||
|
|||
if (prop) { |
|||
init_property(&prop->hdr, t, NOTIFIER); |
|||
prop->types = types; |
|||
prop->u.notifyfn = fn; |
|||
if (types & NOTIFY_EXTRA_ARG) |
|||
EXTRA_ARG(prop) = extra_arg; |
|||
} |
|||
return prop; |
|||
} |
|||
|
|||
static enum tal_notify_type del_notifier_property(struct tal_hdr *t, |
|||
void (*fn)(tal_t *, |
|||
enum tal_notify_type, |
|||
void *), |
|||
bool match_extra_arg, |
|||
void *extra_arg) |
|||
{ |
|||
struct prop_hdr **p; |
|||
|
|||
for (p = (struct prop_hdr **)&t->prop; *p; p = &(*p)->next) { |
|||
struct notifier *n; |
|||
enum tal_notify_type types; |
|||
|
|||
if (is_literal(*p)) |
|||
break; |
|||
if ((*p)->type != NOTIFIER) |
|||
continue; |
|||
n = (struct notifier *)*p; |
|||
if (n->u.notifyfn != fn) |
|||
continue; |
|||
|
|||
types = n->types; |
|||
if ((types & NOTIFY_EXTRA_ARG) |
|||
&& match_extra_arg |
|||
&& extra_arg != EXTRA_ARG(n)) |
|||
continue; |
|||
|
|||
*p = (*p)->next; |
|||
freefn(n); |
|||
return types & ~(NOTIFY_IS_DESTRUCTOR|NOTIFY_EXTRA_ARG); |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
static struct name *add_name_property(struct tal_hdr *t, const char *name) |
|||
{ |
|||
struct name *prop; |
|||
|
|||
prop = allocate(sizeof(*prop) + strlen(name) + 1); |
|||
if (prop) { |
|||
init_property(&prop->hdr, t, NAME); |
|||
strcpy(prop->name, name); |
|||
} |
|||
return prop; |
|||
} |
|||
|
|||
static struct children *add_child_property(struct tal_hdr *parent, |
|||
struct tal_hdr *child UNNEEDED) |
|||
{ |
|||
struct children *prop = allocate(sizeof(*prop)); |
|||
if (prop) { |
|||
init_property(&prop->hdr, parent, CHILDREN); |
|||
prop->parent = parent; |
|||
list_head_init(&prop->children); |
|||
} |
|||
return prop; |
|||
} |
|||
|
|||
static bool add_child(struct tal_hdr *parent, struct tal_hdr *child) |
|||
{ |
|||
struct children *children = find_property(parent, CHILDREN); |
|||
|
|||
if (!children) { |
|||
children = add_child_property(parent, child); |
|||
if (!children) |
|||
return false; |
|||
} |
|||
list_add(&children->children, &child->list); |
|||
child->parent_child = (intptr_t)children ^ TAL_PTR_OBFUSTICATOR; |
|||
return true; |
|||
} |
|||
|
|||
static void del_tree(struct tal_hdr *t, const tal_t *orig, int saved_errno) |
|||
{ |
|||
struct prop_hdr **prop, *p, *next; |
|||
|
|||
assert(!taken(from_tal_hdr(t))); |
|||
|
|||
/* Already being destroyed? Don't loop. */ |
|||
if (unlikely(get_destroying_bit(t->parent_child))) |
|||
return; |
|||
|
|||
set_destroying_bit(&t->parent_child); |
|||
|
|||
/* Call free notifiers. */ |
|||
notify(t, TAL_NOTIFY_FREE, (tal_t *)orig, saved_errno); |
|||
|
|||
/* Now free children and groups. */ |
|||
prop = find_property_ptr(t, CHILDREN); |
|||
if (prop) { |
|||
struct tal_hdr *i; |
|||
struct children *c = (struct children *)*prop; |
|||
|
|||
while ((i = list_top(&c->children, struct tal_hdr, list))) { |
|||
list_del(&i->list); |
|||
del_tree(i, orig, saved_errno); |
|||
} |
|||
} |
|||
|
|||
/* Finally free our properties. */ |
|||
for (p = t->prop; p && !is_literal(p); p = next) { |
|||
next = p->next; |
|||
freefn(p); |
|||
} |
|||
freefn(t); |
|||
} |
|||
|
|||
void *tal_alloc_(const tal_t *ctx, size_t size, bool clear, const char *label) |
|||
{ |
|||
struct tal_hdr *child, *parent = debug_tal(to_tal_hdr_or_null(ctx)); |
|||
|
|||
child = allocate(sizeof(struct tal_hdr) + size); |
|||
if (!child) |
|||
return NULL; |
|||
if (clear) |
|||
memset(from_tal_hdr(child), 0, size); |
|||
child->prop = (void *)label; |
|||
child->bytelen = size; |
|||
|
|||
if (!add_child(parent, child)) { |
|||
freefn(child); |
|||
return NULL; |
|||
} |
|||
debug_tal(parent); |
|||
if (notifiers) |
|||
notify(parent, TAL_NOTIFY_ADD_CHILD, from_tal_hdr(child), 0); |
|||
return from_tal_hdr(debug_tal(child)); |
|||
} |
|||
|
|||
static bool adjust_size(size_t *size, size_t count) |
|||
{ |
|||
const size_t extra = sizeof(struct tal_hdr); |
|||
|
|||
/* Multiplication wrap */ |
|||
if (count && unlikely(*size * count / *size != count)) |
|||
goto overflow; |
|||
|
|||
*size *= count; |
|||
|
|||
/* Make sure we don't wrap adding header. */ |
|||
if (*size + extra < extra) |
|||
goto overflow; |
|||
return true; |
|||
overflow: |
|||
call_error("allocation size overflow"); |
|||
return false; |
|||
} |
|||
|
|||
void *tal_alloc_arr_(const tal_t *ctx, size_t size, size_t count, bool clear, |
|||
const char *label) |
|||
{ |
|||
if (!adjust_size(&size, count)) |
|||
return NULL; |
|||
|
|||
return tal_alloc_(ctx, size, clear, label); |
|||
} |
|||
|
|||
void *tal_free(const tal_t *ctx) |
|||
{ |
|||
if (ctx) { |
|||
struct tal_hdr *t; |
|||
int saved_errno = errno; |
|||
t = debug_tal(to_tal_hdr(ctx)); |
|||
if (unlikely(get_destroying_bit(t->parent_child))) |
|||
return NULL; |
|||
if (notifiers) |
|||
notify(ignore_destroying_bit(t->parent_child)->parent, |
|||
TAL_NOTIFY_DEL_CHILD, ctx, saved_errno); |
|||
list_del(&t->list); |
|||
del_tree(t, ctx, saved_errno); |
|||
errno = saved_errno; |
|||
} |
|||
return NULL; |
|||
} |
|||
|
|||
void *tal_steal_(const tal_t *new_parent, const tal_t *ctx) |
|||
{ |
|||
if (ctx) { |
|||
struct tal_hdr *newpar, *t, *old_parent; |
|||
|
|||
newpar = debug_tal(to_tal_hdr_or_null(new_parent)); |
|||
t = debug_tal(to_tal_hdr(ctx)); |
|||
|
|||
/* Unlink it from old parent. */ |
|||
list_del(&t->list); |
|||
old_parent = ignore_destroying_bit(t->parent_child)->parent; |
|||
|
|||
if (unlikely(!add_child(newpar, t))) { |
|||
/* We can always add to old parent, because it has a
|
|||
* children property already. */ |
|||
if (!add_child(old_parent, t)) |
|||
abort(); |
|||
return NULL; |
|||
} |
|||
debug_tal(newpar); |
|||
if (notifiers) |
|||
notify(t, TAL_NOTIFY_STEAL, new_parent, 0); |
|||
} |
|||
return (void *)ctx; |
|||
} |
|||
|
|||
bool tal_add_destructor_(const tal_t *ctx, void (*destroy)(void *me)) |
|||
{ |
|||
tal_t *t = debug_tal(to_tal_hdr(ctx)); |
|||
return add_notifier_property(t, TAL_NOTIFY_FREE|NOTIFY_IS_DESTRUCTOR, |
|||
(void *)destroy, NULL); |
|||
} |
|||
|
|||
bool tal_add_destructor2_(const tal_t *ctx, void (*destroy)(void *me, void *arg), |
|||
void *arg) |
|||
{ |
|||
tal_t *t = debug_tal(to_tal_hdr(ctx)); |
|||
return add_notifier_property(t, TAL_NOTIFY_FREE|NOTIFY_IS_DESTRUCTOR |
|||
|NOTIFY_EXTRA_ARG, |
|||
(void *)destroy, arg); |
|||
} |
|||
|
|||
/* We could support notifiers with an extra arg, but we didn't add to API */ |
|||
bool tal_add_notifier_(const tal_t *ctx, enum tal_notify_type types, |
|||
void (*callback)(tal_t *, enum tal_notify_type, void *)) |
|||
{ |
|||
struct tal_hdr *t = debug_tal(to_tal_hdr_or_null(ctx)); |
|||
struct notifier *n; |
|||
|
|||
assert(types); |
|||
assert((types & ~(TAL_NOTIFY_FREE | TAL_NOTIFY_STEAL | TAL_NOTIFY_MOVE |
|||
| TAL_NOTIFY_RESIZE | TAL_NOTIFY_RENAME |
|||
| TAL_NOTIFY_ADD_CHILD | TAL_NOTIFY_DEL_CHILD |
|||
| TAL_NOTIFY_ADD_NOTIFIER |
|||
| TAL_NOTIFY_DEL_NOTIFIER)) == 0); |
|||
|
|||
/* Don't call notifier about itself: set types after! */ |
|||
n = add_notifier_property(t, 0, callback, NULL); |
|||
if (unlikely(!n)) |
|||
return false; |
|||
|
|||
if (notifiers) |
|||
notify(t, TAL_NOTIFY_ADD_NOTIFIER, callback, 0); |
|||
|
|||
n->types = types; |
|||
if (types != TAL_NOTIFY_FREE) |
|||
notifiers++; |
|||
return true; |
|||
} |
|||
|
|||
bool tal_del_notifier_(const tal_t *ctx, |
|||
void (*callback)(tal_t *, enum tal_notify_type, void *), |
|||
bool match_extra_arg, void *extra_arg) |
|||
{ |
|||
struct tal_hdr *t = debug_tal(to_tal_hdr_or_null(ctx)); |
|||
enum tal_notify_type types; |
|||
|
|||
types = del_notifier_property(t, callback, match_extra_arg, extra_arg); |
|||
if (types) { |
|||
notify(t, TAL_NOTIFY_DEL_NOTIFIER, callback, 0); |
|||
if (types != TAL_NOTIFY_FREE) |
|||
notifiers--; |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
bool tal_del_destructor_(const tal_t *ctx, void (*destroy)(void *me)) |
|||
{ |
|||
return tal_del_notifier_(ctx, (void *)destroy, false, NULL); |
|||
} |
|||
|
|||
bool tal_del_destructor2_(const tal_t *ctx, void (*destroy)(void *me, void *arg), |
|||
void *arg) |
|||
{ |
|||
return tal_del_notifier_(ctx, (void *)destroy, true, arg); |
|||
} |
|||
|
|||
bool tal_set_name_(tal_t *ctx, const char *name, bool literal) |
|||
{ |
|||
struct tal_hdr *t = debug_tal(to_tal_hdr(ctx)); |
|||
struct prop_hdr **prop = find_property_ptr(t, NAME); |
|||
|
|||
/* Get rid of any old name */ |
|||
if (prop) { |
|||
struct name *name = (struct name *)*prop; |
|||
if (is_literal(&name->hdr)) |
|||
*prop = NULL; |
|||
else { |
|||
*prop = name->hdr.next; |
|||
freefn(name); |
|||
} |
|||
} |
|||
|
|||
if (literal && name[0]) { |
|||
struct prop_hdr **p; |
|||
|
|||
/* Append literal. */ |
|||
for (p = &t->prop; *p && !is_literal(*p); p = &(*p)->next); |
|||
*p = (struct prop_hdr *)name; |
|||
} else if (!add_name_property(t, name)) |
|||
return false; |
|||
|
|||
debug_tal(t); |
|||
if (notifiers) |
|||
notify(t, TAL_NOTIFY_RENAME, name, 0); |
|||
return true; |
|||
} |
|||
|
|||
const char *tal_name(const tal_t *t) |
|||
{ |
|||
struct name *n; |
|||
|
|||
n = find_property(debug_tal(to_tal_hdr(t)), NAME); |
|||
if (!n) |
|||
return NULL; |
|||
|
|||
if (is_literal(&n->hdr)) |
|||
return (const char *)n; |
|||
return n->name; |
|||
} |
|||
|
|||
size_t tal_bytelen(const tal_t *ptr) |
|||
{ |
|||
/* NULL -> null_parent which has bytelen 0 */ |
|||
struct tal_hdr *t = debug_tal(to_tal_hdr_or_null(ptr)); |
|||
|
|||
return t->bytelen; |
|||
} |
|||
|
|||
/* Start one past first child: make stopping natural in circ. list. */ |
|||
static struct tal_hdr *first_child(struct tal_hdr *parent) |
|||
{ |
|||
struct children *child; |
|||
|
|||
child = find_property(parent, CHILDREN); |
|||
if (!child) |
|||
return NULL; |
|||
|
|||
return list_top(&child->children, struct tal_hdr, list); |
|||
} |
|||
|
|||
tal_t *tal_first(const tal_t *root) |
|||
{ |
|||
struct tal_hdr *c, *t = debug_tal(to_tal_hdr_or_null(root)); |
|||
|
|||
c = first_child(t); |
|||
if (!c) |
|||
return NULL; |
|||
return from_tal_hdr(c); |
|||
} |
|||
|
|||
tal_t *tal_next(const tal_t *prev) |
|||
{ |
|||
struct tal_hdr *next, *prevhdr = debug_tal(to_tal_hdr(prev)); |
|||
struct list_head *head; |
|||
|
|||
head = &ignore_destroying_bit(prevhdr->parent_child)->children; |
|||
next = list_next(head, prevhdr, list); |
|||
if (!next) |
|||
return NULL; |
|||
return from_tal_hdr(next); |
|||
} |
|||
|
|||
tal_t *tal_parent(const tal_t *ctx) |
|||
{ |
|||
struct tal_hdr *t; |
|||
|
|||
if (!ctx) |
|||
return NULL; |
|||
|
|||
t = debug_tal(to_tal_hdr(ctx)); |
|||
if (ignore_destroying_bit(t->parent_child)->parent == &null_parent.hdr) |
|||
return NULL; |
|||
return from_tal_hdr(ignore_destroying_bit(t->parent_child)->parent); |
|||
} |
|||
|
|||
bool tal_resize_(tal_t **ctxp, size_t size, size_t count, bool clear) |
|||
{ |
|||
struct tal_hdr *old_t, *t; |
|||
struct children *child; |
|||
|
|||
old_t = debug_tal(to_tal_hdr(*ctxp)); |
|||
|
|||
if (!adjust_size(&size, count)) |
|||
return false; |
|||
|
|||
t = resizefn(old_t, sizeof(struct tal_hdr) + size); |
|||
if (!t) { |
|||
call_error("Reallocation failure"); |
|||
return false; |
|||
} |
|||
|
|||
/* Clear between old end and new end. */ |
|||
if (clear && size > t->bytelen) { |
|||
char *old_end = (char *)(t + 1) + t->bytelen; |
|||
memset(old_end, 0, size - t->bytelen); |
|||
} |
|||
|
|||
/* Update length. */ |
|||
t->bytelen = size; |
|||
update_bounds(t, sizeof(struct tal_hdr) + size); |
|||
|
|||
/* If it didn't move, we're done! */ |
|||
if (t != old_t) { |
|||
/* Fix up linked list pointers. */ |
|||
t->list.next->prev = t->list.prev->next = &t->list; |
|||
|
|||
/* Copy take() property. */ |
|||
if (taken(from_tal_hdr(old_t))) |
|||
take(from_tal_hdr(t)); |
|||
|
|||
/* Fix up child property's parent pointer. */ |
|||
child = find_property(t, CHILDREN); |
|||
if (child) { |
|||
assert(child->parent == old_t); |
|||
child->parent = t; |
|||
} |
|||
*ctxp = from_tal_hdr(debug_tal(t)); |
|||
if (notifiers) |
|||
notify(t, TAL_NOTIFY_MOVE, from_tal_hdr(old_t), 0); |
|||
} |
|||
if (notifiers) |
|||
notify(t, TAL_NOTIFY_RESIZE, (void *)size, 0); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
bool tal_expand_(tal_t **ctxp, const void *src, size_t size, size_t count) |
|||
{ |
|||
size_t old_len; |
|||
bool ret = false; |
|||
|
|||
old_len = debug_tal(to_tal_hdr(*ctxp))->bytelen; |
|||
|
|||
/* Check for additive overflow */ |
|||
if (old_len + count * size < old_len) { |
|||
call_error("dup size overflow"); |
|||
goto out; |
|||
} |
|||
|
|||
/* Don't point src inside thing we're expanding! */ |
|||
assert(src < *ctxp |
|||
|| (char *)src >= (char *)(*ctxp) + old_len); |
|||
|
|||
if (!tal_resize_(ctxp, size, old_len/size + count, false)) |
|||
goto out; |
|||
|
|||
memcpy((char *)*ctxp + old_len, src, count * size); |
|||
ret = true; |
|||
|
|||
out: |
|||
if (taken(src)) |
|||
tal_free(src); |
|||
return ret; |
|||
} |
|||
|
|||
void *tal_dup_(const tal_t *ctx, const void *p, size_t size, |
|||
size_t n, size_t extra, bool nullok, const char *label) |
|||
{ |
|||
void *ret; |
|||
size_t nbytes = size; |
|||
|
|||
if (nullok && p == NULL) { |
|||
/* take(NULL) works. */ |
|||
(void)taken(p); |
|||
return NULL; |
|||
} |
|||
|
|||
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_resize_((void **)&p, size, n + extra, false))) |
|||
return tal_free(p); |
|||
if (unlikely(!tal_steal(ctx, p))) |
|||
return tal_free(p); |
|||
return (void *)p; |
|||
} |
|||
|
|||
ret = tal_alloc_arr_(ctx, size, n + extra, false, label); |
|||
if (ret) |
|||
memcpy(ret, p, nbytes); |
|||
return ret; |
|||
} |
|||
|
|||
void *tal_dup_talarr_(const tal_t *ctx, const tal_t *src TAKES, const char *label) |
|||
{ |
|||
return tal_dup_(ctx, src, 1, tal_bytelen(src), 0, true, label); |
|||
} |
|||
|
|||
void tal_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)) |
|||
{ |
|||
if (alloc_fn) |
|||
allocfn = alloc_fn; |
|||
if (resize_fn) |
|||
resizefn = resize_fn; |
|||
if (free_fn) |
|||
freefn = free_fn; |
|||
if (error_fn) |
|||
errorfn = error_fn; |
|||
} |
|||
|
|||
#ifdef CCAN_TAL_DEBUG |
|||
static void dump_node(unsigned int indent, const struct tal_hdr *t) |
|||
{ |
|||
unsigned int i; |
|||
const struct prop_hdr *p; |
|||
|
|||
for (i = 0; i < indent; i++) |
|||
fprintf(stderr, " "); |
|||
fprintf(stderr, "%p len=%zu", t, t->bytelen); |
|||
for (p = t->prop; p; p = p->next) { |
|||
struct children *c; |
|||
struct name *n; |
|||
struct notifier *no; |
|||
if (is_literal(p)) { |
|||
fprintf(stderr, " \"%s\"", (const char *)p); |
|||
break; |
|||
} |
|||
switch (p->type) { |
|||
case CHILDREN: |
|||
c = (struct children *)p; |
|||
fprintf(stderr, " CHILDREN(%p):parent=%p,children={%p,%p}", |
|||
p, c->parent, |
|||
c->children.n.prev, c->children.n.next); |
|||
break; |
|||
case NAME: |
|||
n = (struct name *)p; |
|||
fprintf(stderr, " NAME(%p):%s", p, n->name); |
|||
break; |
|||
case NOTIFIER: |
|||
no = (struct notifier *)p; |
|||
fprintf(stderr, " NOTIFIER(%p):fn=%p", p, no->u.notifyfn); |
|||
break; |
|||
default: |
|||
fprintf(stderr, " **UNKNOWN(%p):%i**", p, p->type); |
|||
} |
|||
} |
|||
fprintf(stderr, "\n"); |
|||
} |
|||
|
|||
static void tal_dump_(unsigned int level, const struct tal_hdr *t) |
|||
{ |
|||
struct children *children; |
|||
|
|||
dump_node(level, t); |
|||
|
|||
children = find_property(t, CHILDREN); |
|||
if (children) { |
|||
struct tal_hdr *i; |
|||
|
|||
list_for_each(&children->children, i, list) |
|||
tal_dump_(level + 1, i); |
|||
} |
|||
} |
|||
|
|||
void tal_dump(void) |
|||
{ |
|||
tal_dump_(0, &null_parent.hdr); |
|||
} |
|||
#endif /* CCAN_TAL_DEBUG */ |
|||
|
|||
#ifndef NDEBUG |
|||
static bool check_err(struct tal_hdr *t, const char *errorstr, |
|||
const char *errmsg) |
|||
{ |
|||
if (errorstr) { |
|||
/* Try not to malloc: it may be corrupted. */ |
|||
char msg[strlen(errorstr) + 20 + strlen(errmsg) + 1]; |
|||
sprintf(msg, "%s:%p %s", errorstr, from_tal_hdr(t), errmsg); |
|||
call_error(msg); |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
static bool check_node(struct children *parent_child, |
|||
struct tal_hdr *t, const char *errorstr) |
|||
{ |
|||
struct prop_hdr *p; |
|||
struct name *name = NULL; |
|||
struct children *children = NULL; |
|||
|
|||
if (!in_bounds(t)) |
|||
return check_err(t, errorstr, "invalid pointer"); |
|||
|
|||
if (ignore_destroying_bit(t->parent_child) != parent_child) |
|||
return check_err(t, errorstr, "incorrect parent"); |
|||
|
|||
for (p = t->prop; p; p = p->next) { |
|||
if (is_literal(p)) { |
|||
if (name) |
|||
return check_err(t, errorstr, |
|||
"has extra literal"); |
|||
break; |
|||
} |
|||
if (!in_bounds(p)) |
|||
return check_err(t, errorstr, |
|||
"has bad property pointer"); |
|||
|
|||
switch (p->type) { |
|||
case CHILDREN: |
|||
if (children) |
|||
return check_err(t, errorstr, |
|||
"has two child nodes"); |
|||
children = (struct children *)p; |
|||
break; |
|||
case NOTIFIER: |
|||
break; |
|||
case NAME: |
|||
if (name) |
|||
return check_err(t, errorstr, |
|||
"has two names"); |
|||
name = (struct name *)p; |
|||
break; |
|||
default: |
|||
return check_err(t, errorstr, "has unknown property"); |
|||
} |
|||
} |
|||
if (children) { |
|||
struct tal_hdr *i; |
|||
|
|||
if (!list_check(&children->children, errorstr)) |
|||
return false; |
|||
list_for_each(&children->children, i, list) { |
|||
if (!check_node(children, i, errorstr)) |
|||
return false; |
|||
} |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
bool tal_check(const tal_t *ctx, const char *errorstr) |
|||
{ |
|||
struct tal_hdr *t = to_tal_hdr_or_null(ctx); |
|||
|
|||
return check_node(ignore_destroying_bit(t->parent_child), t, errorstr); |
|||
} |
|||
#else /* NDEBUG */ |
|||
bool tal_check(const tal_t *ctx, const char *errorstr) |
|||
{ |
|||
return true; |
|||
} |
|||
#endif |
@ -0,0 +1,553 @@ |
|||
/* Licensed under BSD-MIT - see LICENSE file for details */ |
|||
#ifndef CCAN_TAL_H |
|||
#define CCAN_TAL_H |
|||
#include "config.h" |
|||
#include "compiler.h" |
|||
#include "likely.h" |
|||
#include "typesafe_cb.h" |
|||
#include "str.h" |
|||
#include "take.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 void 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. |
|||
* |
|||
* tal_count() of the return will be 1. |
|||
* |
|||
* Example: |
|||
* int *p = tal(NULL, int); |
|||
* *p = 1; |
|||
*/ |
|||
#define tal(ctx, type) \ |
|||
tal_label(ctx, type, 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) \ |
|||
talz_label(ctx, type, 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, and also saved and restored |
|||
* for any destructors or notifiers. |
|||
* |
|||
* Example: |
|||
* p = tal_free(p); |
|||
*/ |
|||
void *tal_free(const tal_t *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. |
|||
* |
|||
* tal_count() of the returned pointer will be @count. |
|||
* |
|||
* Example: |
|||
* p = tal_arr(NULL, int, 2); |
|||
* p[0] = 0; |
|||
* p[1] = 1; |
|||
*/ |
|||
#define tal_arr(ctx, type, count) \ |
|||
tal_arr_label(ctx, type, count, 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. |
|||
* |
|||
* Equivalent to tal_arr() followed by memset() to zero. |
|||
* |
|||
* Example: |
|||
* p = tal_arrz(NULL, int, 2); |
|||
* assert(p[0] == 0 && p[1] == 0); |
|||
*/ |
|||
#define tal_arrz(ctx, type, count) \ |
|||
tal_arrz_label(ctx, type, count, TAL_LABEL(type, "[]")) |
|||
|
|||
/**
|
|||
* tal_resize - enlarge or reduce a tal object. |
|||
* @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. |
|||
* On success, tal_count() of *@p will be @count. |
|||
* |
|||
* Note: if *p is take(), it will still be take() upon return, even if it |
|||
* has been moved. |
|||
* |
|||
* Example: |
|||
* tal_resize(&p, 100); |
|||
*/ |
|||
#define tal_resize(p, count) \ |
|||
tal_resize_((void **)(p), sizeof**(p), (count), false) |
|||
|
|||
/**
|
|||
* tal_resizez - enlarge or reduce a tal object; zero out extra. |
|||
* @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. |
|||
* |
|||
* Example: |
|||
* tal_resizez(&p, 200); |
|||
*/ |
|||
#define tal_resizez(p, count) \ |
|||
tal_resize_((void **)(p), sizeof**(p), (count), true) |
|||
|
|||
/**
|
|||
* tal_steal - change the parent of a tal-allocated pointer. |
|||
* @ctx: The new parent. |
|||
* @ptr: The tal allocated object to move, or NULL. |
|||
* |
|||
* This may need to perform an allocation, in which case it may fail; thus |
|||
* it can return NULL, otherwise returns @ptr. If @ptr is NULL, this function does |
|||
* nothing. |
|||
*/ |
|||
#if HAVE_STATEMENT_EXPR |
|||
/* Weird macro avoids gcc's 'warning: value computed is not used'. */ |
|||
#define tal_steal(ctx, ptr) \ |
|||
({ (tal_typeof(ptr) tal_steal_((ctx),(ptr))); }) |
|||
#else |
|||
#define tal_steal(ctx, ptr) \ |
|||
(tal_typeof(ptr) tal_steal_((ctx),(ptr))) |
|||
#endif |
|||
|
|||
/**
|
|||
* 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. |
|||
* |
|||
* Note that this can only fail if your allocfn fails and your errorfn returns. |
|||
*/ |
|||
#define tal_add_destructor(ptr, function) \ |
|||
tal_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 that if we're inside the destructor call itself, this will |
|||
* return false. |
|||
*/ |
|||
#define tal_del_destructor(ptr, function) \ |
|||
tal_del_destructor_((ptr), typesafe_cb(void, void *, (function), (ptr))) |
|||
|
|||
/**
|
|||
* tal_add_destructor2 - add a 2-arg callback function when context is destroyed. |
|||
* @ptr: The tal allocated object. |
|||
* @function: the function to call before it's freed. |
|||
* @arg: the extra argument to the function. |
|||
* |
|||
* Sometimes an extra argument is required for a destructor; this |
|||
* saves the extra argument internally to avoid the caller having to |
|||
* do an extra allocation. |
|||
* |
|||
* Note that this can only fail if your allocfn fails and your errorfn returns. |
|||
*/ |
|||
#define tal_add_destructor2(ptr, function, arg) \ |
|||
tal_add_destructor2_((ptr), \ |
|||
typesafe_cb_cast(void (*)(tal_t *, void *), \ |
|||
void (*)(__typeof__(ptr), \ |
|||
__typeof__(arg)), \ |
|||
(function)), \ |
|||
(arg)) |
|||
|
|||
/**
|
|||
* 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 that if we're inside the destructor call itself, this will |
|||
* return false. |
|||
*/ |
|||
#define tal_del_destructor(ptr, function) \ |
|||
tal_del_destructor_((ptr), typesafe_cb(void, void *, (function), (ptr))) |
|||
|
|||
/**
|
|||
* tal_del_destructor2 - remove 2-arg callback function. |
|||
* @ptr: The tal allocated object. |
|||
* @function: the function to call before it's freed. |
|||
* @arg: the extra argument to the function. |
|||
* |
|||
* If @function has not been successfully added as a destructor with |
|||
* @arg, this returns false. |
|||
*/ |
|||
#define tal_del_destructor2(ptr, function, arg) \ |
|||
tal_del_destructor2_((ptr), \ |
|||
typesafe_cb_cast(void (*)(tal_t *, void *), \ |
|||
void (*)(__typeof__(ptr), \ |
|||
__typeof__(arg)), \ |
|||
(function)), \ |
|||
(arg)) |
|||
enum tal_notify_type { |
|||
TAL_NOTIFY_FREE = 1, |
|||
TAL_NOTIFY_STEAL = 2, |
|||
TAL_NOTIFY_MOVE = 4, |
|||
TAL_NOTIFY_RESIZE = 8, |
|||
TAL_NOTIFY_RENAME = 16, |
|||
TAL_NOTIFY_ADD_CHILD = 32, |
|||
TAL_NOTIFY_DEL_CHILD = 64, |
|||
TAL_NOTIFY_ADD_NOTIFIER = 128, |
|||
TAL_NOTIFY_DEL_NOTIFIER = 256 |
|||
}; |
|||
|
|||
/**
|
|||
* tal_add_notifier - add a callback function when this context changes. |
|||
* @ptr: The tal allocated object, or NULL. |
|||
* @types: Bitwise OR of the types the callback is interested in. |
|||
* @callback: the function to call. |
|||
* |
|||
* Note that this can only fail if your allocfn fails and your errorfn |
|||
* returns. Also note that notifiers are not reliable in the case |
|||
* where an allocation fails, as they may be called before any |
|||
* allocation is actually done. |
|||
* |
|||
* TAL_NOTIFY_FREE is called when @ptr is freed, either directly or |
|||
* because an ancestor is freed: @info is the argument to tal_free(). |
|||
* It is exactly equivalent to a destructor, with more information. |
|||
* errno is set to the value it was at the call of tal_free(). |
|||
* |
|||
* TAL_NOTIFY_STEAL is called when @ptr's parent changes: @info is the |
|||
* new parent. |
|||
* |
|||
* TAL_NOTIFY_MOVE is called when @ptr is realloced (via tal_resize) |
|||
* and moved. In this case, @ptr arg here is the new memory, and |
|||
* @info is the old pointer. |
|||
* |
|||
* TAL_NOTIFY_RESIZE is called when @ptr is realloced via tal_resize: |
|||
* @info is the new size, in bytes. If the pointer has moved, |
|||
* TAL_NOTIFY_MOVE callbacks are called first. |
|||
* |
|||
* TAL_NOTIFY_ADD_CHILD/TAL_NOTIFY_DEL_CHILD are called when @ptr is |
|||
* the context for a tal() allocating call, or a direct child is |
|||
* tal_free()d: @info is the child. Note that TAL_NOTIFY_DEL_CHILD is |
|||
* not called when this context is tal_free()d: TAL_NOTIFY_FREE is |
|||
* considered sufficient for that case. |
|||
* |
|||
* TAL_NOTIFY_ADD_NOTIFIER/TAL_NOTIFIER_DEL_NOTIFIER are called when a |
|||
* notifier is added or removed (not for this notifier): @info is the |
|||
* callback. This is also called for tal_add_destructor and |
|||
* tal_del_destructor. |
|||
*/ |
|||
#define tal_add_notifier(ptr, types, callback) \ |
|||
tal_add_notifier_((ptr), (types), \ |
|||
typesafe_cb_postargs(void, tal_t *, (callback), \ |
|||
(ptr), \ |
|||
enum tal_notify_type, void *)) |
|||
|
|||
/**
|
|||
* tal_del_notifier - remove a notifier callback function. |
|||
* @ptr: The tal allocated object. |
|||
* @callback: the function to call. |
|||
*/ |
|||
#define tal_del_notifier(ptr, callback) \ |
|||
tal_del_notifier_((ptr), \ |
|||
typesafe_cb_postargs(void, void *, (callback), \ |
|||
(ptr), \ |
|||
enum tal_notify_type, void *), \ |
|||
false, NULL) |
|||
|
|||
/**
|
|||
* 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_set_name_((ptr), (name), TAL_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. |
|||
*/ |
|||
const char *tal_name(const tal_t *ptr); |
|||
|
|||
/**
|
|||
* tal_count - get the count of objects in a tal object. |
|||
* @ptr: The tal allocated object (or NULL) |
|||
* |
|||
* Returns 0 if @ptr is NULL. Note that if the allocation was done as a |
|||
* different type to @ptr, the result may not match the @count argument |
|||
* (or implied 1) of that allocation! |
|||
*/ |
|||
#define tal_count(p) (tal_bytelen(p) / sizeof(*p)) |
|||
|
|||
/**
|
|||
* tal_bytelen - get the count of bytes in a tal object. |
|||
* @ptr: The tal allocated object (or NULL) |
|||
* |
|||
* Returns 0 if @ptr is NULL. |
|||
*/ |
|||
size_t tal_bytelen(const tal_t *ptr); |
|||
|
|||
/**
|
|||
* tal_first - get the first immediate tal object child. |
|||
* @root: The tal allocated object to start with, or NULL. |
|||
* |
|||
* Returns NULL if there are no children. |
|||
*/ |
|||
tal_t *tal_first(const tal_t *root); |
|||
|
|||
/**
|
|||
* tal_next - get the next immediate tal object child. |
|||
* @prev: The return value from tal_first or tal_next. |
|||
* |
|||
* Returns NULL if there are no more immediate children. This should be safe to |
|||
* call on an altering tree unless @prev is no longer valid. |
|||
*/ |
|||
tal_t *tal_next(const tal_t *prev); |
|||
|
|||
/**
|
|||
* 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. |
|||
*/ |
|||
tal_t *tal_parent(const tal_t *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()). Must not be NULL. |
|||
*/ |
|||
#define tal_dup(ctx, type, p) \ |
|||
tal_dup_label(ctx, type, p, TAL_LABEL(type, ""), false) |
|||
|
|||
/**
|
|||
* tal_dup_or_null - duplicate an object, or just pass NULL. |
|||
* @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()) |
|||
* |
|||
* if @p is NULL, just return NULL, otherwise to tal_dup(). |
|||
*/ |
|||
#define tal_dup_or_null(ctx, type, p) \ |
|||
tal_dup_label(ctx, type, p, TAL_LABEL(type, ""), true) |
|||
|
|||
/**
|
|||
* 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) \ |
|||
tal_dup_arr_label(ctx, type, p, n, extra, TAL_LABEL(type, "[]")) |
|||
|
|||
|
|||
/**
|
|||
* tal_dup_arr - duplicate a tal 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 tal array to copy (or resized & reparented if take()) |
|||
* |
|||
* The comon case of duplicating an entire tal array. |
|||
*/ |
|||
#define tal_dup_talarr(ctx, type, p) \ |
|||
((type *)tal_dup_talarr_((ctx), tal_typechk_(p, type *), \ |
|||
TAL_LABEL(type, "[]"))) |
|||
/* Lower-level interfaces, where you want to supply your own label string. */ |
|||
#define tal_label(ctx, type, label) \ |
|||
((type *)tal_alloc_((ctx), sizeof(type), false, label)) |
|||
#define talz_label(ctx, type, label) \ |
|||
((type *)tal_alloc_((ctx), sizeof(type), true, label)) |
|||
#define tal_arr_label(ctx, type, count, label) \ |
|||
((type *)tal_alloc_arr_((ctx), sizeof(type), (count), false, label)) |
|||
#define tal_arrz_label(ctx, type, count, label) \ |
|||
((type *)tal_alloc_arr_((ctx), sizeof(type), (count), true, label)) |
|||
#define tal_dup_label(ctx, type, p, label, nullok) \ |
|||
((type *)tal_dup_((ctx), tal_typechk_(p, type *), \ |
|||
sizeof(type), 1, 0, nullok, \ |
|||
label)) |
|||
#define tal_dup_arr_label(ctx, type, p, n, extra, label) \ |
|||
((type *)tal_dup_((ctx), tal_typechk_(p, type *), \ |
|||
sizeof(type), (n), (extra), false, \ |
|||
label)) |
|||
|
|||
/**
|
|||
* tal_set_backend - set the allocation or error functions to use |
|||
* @alloc_fn: allocator or NULL (default is malloc) |
|||
* @resize_fn: re-allocator or NULL (default is realloc) |
|||
* @free_fn: free function or NULL (default is free) |
|||
* @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 erorr_fn to change that. error_fn can return, and is |
|||
* called if alloc_fn or resize_fn fail. |
|||
* |
|||
* If any parameter is NULL, that function is unchanged. |
|||
*/ |
|||
void tal_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)); |
|||
|
|||
/**
|
|||
* 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_expand_((void **)(a1p), (a2), sizeof**(a1p), \ |
|||
(num2) + 0*sizeof(*(a1p) == (a2))) |
|||
|
|||
/**
|
|||
* tal_cleanup - remove pointers from NULL node |
|||
* |
|||
* Internally, tal keeps a list of nodes allocated from @ctx NULL; this |
|||
* prevents valgrind from noticing memory leaks. This re-initializes |
|||
* that list to empty. |
|||
* |
|||
* It also calls take_cleanup() for you. |
|||
*/ |
|||
void tal_cleanup(void); |
|||
|
|||
|
|||
/**
|
|||
* tal_check - sanity check a tal context and its children. |
|||
* @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. |
|||
* |
|||
* See also: |
|||
* tal_set_backend() |
|||
*/ |
|||
bool tal_check(const tal_t *ctx, const char *errorstr); |
|||
|
|||
#ifdef CCAN_TAL_DEBUG |
|||
/**
|
|||
* tal_dump - dump entire tal tree to stderr. |
|||
* |
|||
* This is a helper for debugging tal itself, which dumps all the tal internal |
|||
* state. |
|||
*/ |
|||
void tal_dump(void); |
|||
#endif |
|||
|
|||
/* Internal support functions */ |
|||
#ifndef TAL_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_IS_LITERAL(str) __builtin_constant_p(str) |
|||
#else |
|||
#define TAL_IS_LITERAL(str) (sizeof(&*(str)) != sizeof(char *)) |
|||
#endif |
|||
|
|||
bool tal_set_name_(tal_t *ctx, const char *name, bool literal); |
|||
|
|||
#if HAVE_TYPEOF |
|||
#define tal_typeof(ptr) (__typeof__(ptr)) |
|||
#if HAVE_STATEMENT_EXPR |
|||
/* Careful: ptr can be const foo *, ptype is foo *. Also, ptr could
|
|||
* be an array, eg "hello". */ |
|||
#define tal_typechk_(ptr, ptype) ({ __typeof__((ptr)+0) _p = (ptype)(ptr); _p; }) |
|||
#else |
|||
#define tal_typechk_(ptr, ptype) (ptr) |
|||
#endif |
|||
#else /* !HAVE_TYPEOF */ |
|||
#define tal_typeof(ptr) |
|||
#define tal_typechk_(ptr, ptype) (ptr) |
|||
#endif |
|||
|
|||
void *tal_alloc_(const tal_t *ctx, size_t bytes, bool clear, const char *label); |
|||
void *tal_alloc_arr_(const tal_t *ctx, size_t bytes, size_t count, bool clear, |
|||
const char *label); |
|||
|
|||
void *tal_dup_(const tal_t *ctx, const void *p TAKES, size_t size, |
|||
size_t n, size_t extra, bool nullok, const char *label); |
|||
void *tal_dup_talarr_(const tal_t *ctx, const tal_t *src TAKES, |
|||
const char *label); |
|||
|
|||
tal_t *tal_steal_(const tal_t *new_parent, const tal_t *t); |
|||
|
|||
bool tal_resize_(tal_t **ctxp, size_t size, size_t count, bool clear); |
|||
bool tal_expand_(tal_t **ctxp, const void *src TAKES, size_t size, size_t count); |
|||
|
|||
bool tal_add_destructor_(const tal_t *ctx, void (*destroy)(void *me)); |
|||
bool tal_add_destructor2_(const tal_t *ctx, void (*destroy)(void *me, void *arg), |
|||
void *arg); |
|||
bool tal_del_destructor_(const tal_t *ctx, void (*destroy)(void *me)); |
|||
bool tal_del_destructor2_(const tal_t *ctx, void (*destroy)(void *me, void *arg), |
|||
void *arg); |
|||
|
|||
bool tal_add_notifier_(const tal_t *ctx, enum tal_notify_type types, |
|||
void (*notify)(tal_t *ctx, enum tal_notify_type, |
|||
void *info)); |
|||
bool tal_del_notifier_(const tal_t *ctx, |
|||
void (*notify)(tal_t *ctx, enum tal_notify_type, |
|||
void *info), |
|||
bool match_extra_arg, void *arg); |
|||
#endif /* CCAN_TAL_H */ |
@ -0,0 +1,315 @@ |
|||
/* 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 "talstr.h" |
|||
#include <sys/types.h> |
|||
#include <regex.h> |
|||
#include <stdarg.h> |
|||
#include <unistd.h> |
|||
#include <stdio.h> |
|||
#include "str.h" |
|||
|
|||
char *tal_strdup_(const tal_t *ctx, const char *p, const char *label) |
|||
{ |
|||
/* We have to let through NULL for take(). */ |
|||
return tal_dup_arr_label(ctx, char, p, p ? strlen(p) + 1: 1, 0, label); |
|||
} |
|||
|
|||
char *tal_strndup_(const tal_t *ctx, const char *p, size_t n, const char *label) |
|||
{ |
|||
size_t len; |
|||
char *ret; |
|||
|
|||
/* We have to let through NULL for take(). */ |
|||
if (likely(p)) |
|||
len = strnlen(p, n); |
|||
else |
|||
len = n; |
|||
|
|||
ret = tal_dup_arr_label(ctx, char, p, len, 1, label); |
|||
if (ret) |
|||
ret[len] = '\0'; |
|||
return ret; |
|||
} |
|||
|
|||
char *tal_fmt_(const tal_t *ctx, const char *label, const char *fmt, ...) |
|||
{ |
|||
va_list ap; |
|||
char *ret; |
|||
|
|||
va_start(ap, fmt); |
|||
ret = tal_vfmt_(ctx, fmt, ap, label); |
|||
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 + 1; |
|||
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; |
|||
/* Make sure tal_count() is correct! */ |
|||
tal_resize(buf, off + ret + 1); |
|||
break; |
|||
} |
|||
max *= 2; |
|||
} |
|||
|
|||
if (taken(fmt)) |
|||
tal_free(fmt); |
|||
return ok; |
|||
} |
|||
|
|||
char *tal_vfmt_(const tal_t *ctx, const char *fmt, va_list ap, const char *label) |
|||
{ |
|||
char *buf; |
|||
|
|||
if (!fmt && taken(fmt)) |
|||
return NULL; |
|||
|
|||
/* A decent guess to start. */ |
|||
buf = tal_arr_label(ctx, char, strlen(fmt) * 2, label); |
|||
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, |
|||
const char *label) |
|||
{ |
|||
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); |
|||
|
|||
ret = tal_dup_arr_label(ctx, char, s1, len1, len2 + 1, label); |
|||
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, |
|||
const char *label) |
|||
{ |
|||
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, |
|||
const char *label) |
|||
{ |
|||
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_label(ctx, char, dlen*2+1, label); |
|||
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'; |
|||
/* Make sure tal_count() is correct! */ |
|||
tal_resize(&ret, totlen+1); |
|||
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 *label, |
|||
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, |
|||
label); |
|||
/* 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; |
|||
} |
@ -0,0 +1,225 @@ |
|||
/* 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 "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()). |
|||
* |
|||
* The returned string will have tal_count() == strlen() + 1. |
|||
*/ |
|||
#define tal_strdup(ctx, p) tal_strdup_(ctx, p, TAL_LABEL(char, "[]")) |
|||
char *tal_strdup_(const tal_t *ctx, const char *p TAKES, const char *label); |
|||
|
|||
/**
|
|||
* 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. |
|||
* The returned string will have tal_count() == strlen() + 1. |
|||
*/ |
|||
#define tal_strndup(ctx, p, n) tal_strndup_(ctx, p, n, TAL_LABEL(char, "[]")) |
|||
char *tal_strndup_(const tal_t *ctx, const char *p TAKES, size_t n, |
|||
const char *label); |
|||
|
|||
/**
|
|||
* tal_fmt - allocate a formatted string |
|||
* @ctx: NULL, or tal allocated object to be parent. |
|||
* @fmt: the printf-style format (can be take()). |
|||
* |
|||
* The returned string will have tal_count() == strlen() + 1. |
|||
*/ |
|||
#define tal_fmt(ctx, ...) \ |
|||
tal_fmt_(ctx, TAL_LABEL(char, "[]"), __VA_ARGS__) |
|||
char *tal_fmt_(const tal_t *ctx, const char *label, const char *fmt TAKES, |
|||
...) PRINTF_FMT(3,4); |
|||
|
|||
/**
|
|||
* 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. |
|||
* |
|||
* The returned string will have tal_count() == strlen() + 1. |
|||
*/ |
|||
#define tal_vfmt(ctx, fmt, va) \ |
|||
tal_vfmt_(ctx, fmt, va, TAL_LABEL(char, "[]")) |
|||
char *tal_vfmt_(const tal_t *ctx, const char *fmt TAKES, va_list ap, |
|||
const char *label) |
|||
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. |
|||
* Otherwise tal_count(*@baseptr) == strlen(*@baseptr) + 1. |
|||
*/ |
|||
bool tal_append_fmt(char **baseptr, const char *fmt TAKES, ...) 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. |
|||
* Otherwise tal_count(*@baseptr) == strlen(*@baseptr) + 1. |
|||
*/ |
|||
bool tal_append_vfmt(char **baseptr, const char *fmt TAKES, 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()). |
|||
* |
|||
* The returned string will have tal_count() == strlen() + 1. |
|||
*/ |
|||
#define tal_strcat(ctx, s1, s2) tal_strcat_(ctx, s1, s2, TAL_LABEL(char, "[]")) |
|||
char *tal_strcat_(const tal_t *ctx, const char *s1 TAKES, const char *s2 TAKES, |
|||
const char *label); |
|||
|
|||
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; |
|||
* } |
|||
*/ |
|||
#define tal_strsplit(ctx, string, delims, flag) \ |
|||
tal_strsplit_(ctx, string, delims, flag, TAL_LABEL(char *, "[]")) |
|||
char **tal_strsplit_(const tal_t *ctx, |
|||
const char *string TAKES, |
|||
const char *delims TAKES, |
|||
enum strsplit flag, |
|||
const char *label); |
|||
|
|||
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. |
|||
* |
|||
* The returned string will have tal_count() == strlen() + 1. |
|||
* |
|||
* 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; |
|||
* } |
|||
*/ |
|||
#define tal_strjoin(ctx, strings, delim, flags) \ |
|||
tal_strjoin_(ctx, strings, delim, flags, TAL_LABEL(char, "[]")) |
|||
char *tal_strjoin_(const void *ctx, |
|||
char *strings[] TAKES, |
|||
const char *delim TAKES, |
|||
enum strjoin flags, |
|||
const char *label); |
|||
|
|||
/**
|
|||
* 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. |
|||
* The allocated strings will have tal_count() == strlen() + 1. |
|||
* |
|||
* See Also: |
|||
* regcomp(3), regex(3). |
|||
* |
|||
* Example: |
|||
* // Given "My name is Rusty" outputs "Hello Rusty!\n"
|
|||
* // Given "my first name is Rusty Russell" outputs "Hello Rusty Russell!\n"
|
|||
* // Given "My name isnt Rusty Russell" outputs "Hello there!\n"
|
|||
* int main(int argc, char *argv[]) |
|||
* { |
|||
* char *person, *input; |
|||
* |
|||
* (void)argc; |
|||
* // 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; |
|||
* } |
|||
*/ |
|||
#define tal_strreg(ctx, string, ...) \ |
|||
tal_strreg_(ctx, string, TAL_LABEL(char, "[]"), __VA_ARGS__) |
|||
bool tal_strreg_(const void *ctx, const char *string TAKES, |
|||
const char *label, const char *regex, ...); |
|||
#endif /* CCAN_STR_TAL_H */ |
@ -0,0 +1,134 @@ |
|||
/* CC0 (Public domain) - see LICENSE file for details */ |
|||
#ifndef CCAN_TYPESAFE_CB_H |
|||
#define CCAN_TYPESAFE_CB_H |
|||
#include "config.h" |
|||
|
|||
#if HAVE_TYPEOF && HAVE_BUILTIN_CHOOSE_EXPR && HAVE_BUILTIN_TYPES_COMPATIBLE_P |
|||
/**
|
|||
* typesafe_cb_cast - only cast an expression if it matches a given type |
|||
* @desttype: the type to cast to |
|||
* @oktype: the type we allow |
|||
* @expr: the expression to cast |
|||
* |
|||
* This macro is used to create functions which allow multiple types. |
|||
* The result of this macro is used somewhere that a @desttype type is |
|||
* expected: if @expr is exactly of type @oktype, then it will be |
|||
* cast to @desttype type, otherwise left alone. |
|||
* |
|||
* This macro can be used in static initializers. |
|||
* |
|||
* This is merely useful for warnings: if the compiler does not |
|||
* support the primitives required for typesafe_cb_cast(), it becomes an |
|||
* unconditional cast, and the @oktype argument is not used. In |
|||
* particular, this means that @oktype can be a type which uses the |
|||
* "typeof": it will not be evaluated if typeof is not supported. |
|||
* |
|||
* Example: |
|||
* // We can take either an unsigned long or a void *.
|
|||
* void _set_some_value(void *val); |
|||
* #define set_some_value(e) \ |
|||
* _set_some_value(typesafe_cb_cast(void *, unsigned long, (e))) |
|||
*/ |
|||
#define typesafe_cb_cast(desttype, oktype, expr) \ |
|||
__builtin_choose_expr( \ |
|||
__builtin_types_compatible_p(__typeof__(0?(expr):(expr)), \ |
|||
oktype), \ |
|||
(desttype)(expr), (expr)) |
|||
#else |
|||
#define typesafe_cb_cast(desttype, oktype, expr) ((desttype)(expr)) |
|||
#endif |
|||
|
|||
/**
|
|||
* typesafe_cb_cast3 - only cast an expression if it matches given types |
|||
* @desttype: the type to cast to |
|||
* @ok1: the first type we allow |
|||
* @ok2: the second type we allow |
|||
* @ok3: the third type we allow |
|||
* @expr: the expression to cast |
|||
* |
|||
* This is a convenient wrapper for multiple typesafe_cb_cast() calls. |
|||
* You can chain them inside each other (ie. use typesafe_cb_cast() |
|||
* for expr) if you need more than 3 arguments. |
|||
* |
|||
* Example: |
|||
* // We can take either a long, unsigned long, void * or a const void *.
|
|||
* void _set_some_value(void *val); |
|||
* #define set_some_value(expr) \ |
|||
* _set_some_value(typesafe_cb_cast3(void *,, \ |
|||
* long, unsigned long, const void *,\ |
|||
* (expr))) |
|||
*/ |
|||
#define typesafe_cb_cast3(desttype, ok1, ok2, ok3, expr) \ |
|||
typesafe_cb_cast(desttype, ok1, \ |
|||
typesafe_cb_cast(desttype, ok2, \ |
|||
typesafe_cb_cast(desttype, ok3, \ |
|||
(expr)))) |
|||
|
|||
/**
|
|||
* typesafe_cb - cast a callback function if it matches the arg |
|||
* @rtype: the return type of the callback function |
|||
* @atype: the (pointer) type which the callback function expects. |
|||
* @fn: the callback function to cast |
|||
* @arg: the (pointer) argument to hand to the callback function. |
|||
* |
|||
* If a callback function takes a single argument, this macro does |
|||
* appropriate casts to a function which takes a single atype argument if the |
|||
* callback provided matches the @arg. |
|||
* |
|||
* It is assumed that @arg is of pointer type: usually @arg is passed |
|||
* or assigned to a void * elsewhere anyway. |
|||
* |
|||
* Example: |
|||
* void _register_callback(void (*fn)(void *arg), void *arg); |
|||
* #define register_callback(fn, arg) \ |
|||
* _register_callback(typesafe_cb(void, (fn), void*, (arg)), (arg)) |
|||
*/ |
|||
#define typesafe_cb(rtype, atype, fn, arg) \ |
|||
typesafe_cb_cast(rtype (*)(atype), \ |
|||
rtype (*)(__typeof__(arg)), \ |
|||
(fn)) |
|||
|
|||
/**
|
|||
* typesafe_cb_preargs - cast a callback function if it matches the arg |
|||
* @rtype: the return type of the callback function |
|||
* @atype: the (pointer) type which the callback function expects. |
|||
* @fn: the callback function to cast |
|||
* @arg: the (pointer) argument to hand to the callback function. |
|||
* |
|||
* This is a version of typesafe_cb() for callbacks that take other arguments |
|||
* before the @arg. |
|||
* |
|||
* Example: |
|||
* void _register_callback(void (*fn)(int, void *arg), void *arg); |
|||
* #define register_callback(fn, arg) \ |
|||
* _register_callback(typesafe_cb_preargs(void, void *, \ |
|||
* (fn), (arg), int), \ |
|||
* (arg)) |
|||
*/ |
|||
#define typesafe_cb_preargs(rtype, atype, fn, arg, ...) \ |
|||
typesafe_cb_cast(rtype (*)(__VA_ARGS__, atype), \ |
|||
rtype (*)(__VA_ARGS__, __typeof__(arg)), \ |
|||
(fn)) |
|||
|
|||
/**
|
|||
* typesafe_cb_postargs - cast a callback function if it matches the arg |
|||
* @rtype: the return type of the callback function |
|||
* @atype: the (pointer) type which the callback function expects. |
|||
* @fn: the callback function to cast |
|||
* @arg: the (pointer) argument to hand to the callback function. |
|||
* |
|||
* This is a version of typesafe_cb() for callbacks that take other arguments |
|||
* after the @arg. |
|||
* |
|||
* Example: |
|||
* void _register_callback(void (*fn)(void *arg, int), void *arg); |
|||
* #define register_callback(fn, arg) \ |
|||
* _register_callback(typesafe_cb_postargs(void, (fn), void *, \ |
|||
* (arg), int), \ |
|||
* (arg)) |
|||
*/ |
|||
#define typesafe_cb_postargs(rtype, atype, fn, arg, ...) \ |
|||
typesafe_cb_cast(rtype (*)(atype, __VA_ARGS__), \ |
|||
rtype (*)(__typeof__(arg), __VA_ARGS__), \ |
|||
(fn)) |
|||
#endif /* CCAN_CAST_IF_TYPE_H */ |
Loading…
Reference in new issue