commit 389c2c96953e6f36ad1852264692ee5124e51edb
parent 4a6121ba1334466dcf868b62034da3d04990ba83
Author: William Casarin <jb55@jb55.com>
Date: Thu, 25 Jan 2024 14:23:36 -0800
nostrdb: add supporting files before the move commit
Diffstat:
A | nostrdb/bech32.c | | | 217 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | nostrdb/bech32.h | | | 142 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | nostrdb/compiler.h | | | 342 | +++++++++++++------------------------------------------------------------------ |
M | nostrdb/cursor.h | | | 60 | ++++++++++++------------------------------------------------ |
4 files changed, 426 insertions(+), 335 deletions(-)
diff --git a/nostrdb/bech32.c b/nostrdb/bech32.c
@@ -0,0 +1,217 @@
+/* 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_len(char* hrp, uint8_t *data, size_t *data_len, const char *input, size_t input_len) {
+ uint32_t chk = 1;
+ size_t i;
+ size_t hrp_len;
+ int have_lower = 0, have_upper = 0;
+ if (input_len < 8) {
+ 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;
+ }
+}
+
+bech32_encoding bech32_decode(char* hrp, uint8_t *data, size_t *data_len, const char *input, size_t max_input_len) {
+ size_t len = strlen(input);
+ if (len > max_input_len) {
+ return BECH32_ENCODING_NONE;
+ }
+ return bech32_decode_len(hrp, data, data_len, input, len);
+}
+
+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;
+}
diff --git a/nostrdb/bech32.h b/nostrdb/bech32.h
@@ -0,0 +1,142 @@
+/* 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
+);
+
+bech32_encoding bech32_decode_len(
+ char *hrp,
+ uint8_t *data,
+ size_t *data_len,
+ const char *input,
+ size_t 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 */
+
diff --git a/nostrdb/compiler.h b/nostrdb/compiler.h
@@ -1,317 +1,85 @@
-/* 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 COMPILER_H
+#define COMPILER_H
-#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
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include "config.h"
-#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__))
+#if HAVE_UNALIGNED_ACCESS
+#define alignment_ok(p, n) 1
#else
-/* Before used, unused functions and vars were always emitted. */
-#define NEEDED __attribute__((__unused__))
-#endif
+#define alignment_ok(p, n) ((size_t)(p) % (n) == 0)
#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.
+ * BUILD_ASSERT - assert a build-time dependency.
+ * @cond: the compile-time condition which must be true.
*
- * Used to mark a function, type or variable should not be used.
+ * 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:
- * WARN_DEPRECATED char *oldfunc(char *buf);
+ * #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 WARN_DEPRECATED __attribute__((__deprecated__))
-#else
-#define WARN_DEPRECATED
-#endif
-
+#define BUILD_ASSERT(cond) \
+ do { (void) sizeof(char [1 - 2*!(cond)]); } while(0)
-#if HAVE_ATTRIBUTE_NONNULL
/**
- * NO_NULL_ARGS - specify that no arguments to this function can be NULL.
+ * BUILD_ASSERT_OR_ZERO - assert a build-time dependency, as an expression.
+ * @cond: the compile-time condition which must be true.
*
- * The compiler will warn if any pointer args are NULL.
+ * 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:
- * NO_NULL_ARGS char *my_copy(char *buf);
+ * #define foo_to_char(foo) \
+ * ((char *)(foo) \
+ * + BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0))
*/
-#define NO_NULL_ARGS __attribute__((__nonnull__))
+#define BUILD_ASSERT_OR_ZERO(cond) \
+ (sizeof(char [1 - 2*!(cond)]) - 1)
-/**
- * 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
+#define memclear(mem, size) memset(mem, 0, size)
+#define memclear_2(m1, s1, m2, s2) { memclear(m1, s1); memclear(m2, s2); }
+#define memclear_3(m1, s1, m2, s2, m3, s3) { memclear(m1, s1); memclear(m2, s2); memclear(m3, s3); }
-#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
+static inline void *memcheck_(const void *data, size_t len)
+{
+ (void)len;
+ return (void *)data;
+}
-#if HAVE_ATTRIBUTE_SENTINEL
+#if HAVE_TYPEOF
/**
- * LAST_ARG_NULL - specify the last argument of a variadic function must be NULL.
+ * memcheck - check that a memory region is initialized
+ * @data: start of region
+ * @len: length in bytes
*
- * The compiler will warn if the last argument isn't NULL.
+ * 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:
- * char *join_string(char *buf, ...) LAST_ARG_NULL;
+ * // Search for space, but make sure it's all initialized.
+ * if (memchr(memcheck(somebytes, bytes_len), ' ', bytes_len)) {
+ * printf("space was found!\n");
+ * }
*/
-#define LAST_ARG_NULL __attribute__((__sentinel__))
+#define memcheck(data, len) ((__typeof__((data)+0))memcheck_((data), (len)))
#else
-#define LAST_ARG_NULL
+#define memcheck(data, len) memcheck_((data), (len))
#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 */
+#endif /* COMPILER_H */
diff --git a/nostrdb/cursor.h b/nostrdb/cursor.h
@@ -3,7 +3,6 @@
#define JB55_CURSOR_H
#include "typedefs.h"
-#include "varint.h"
#include <stdio.h>
#include <ctype.h>
@@ -484,37 +483,11 @@ static inline int parse_str(struct cursor *cur, const char *str) {
return 1;
}
-static inline int is_whitespace(int c) {
+static inline int is_whitespace(char c) {
return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r';
}
-
-static inline int next_char_is_whitespace(unsigned char *curChar, unsigned char *endChar) {
- unsigned char * next = curChar + 1;
- if(next > endChar) return 0;
- else if(next == endChar) return 1;
- return is_whitespace(*next);
-}
-
-static int char_disallowed_at_end_url(char c){
- return c == '.' || c == ',';
-}
-
-static inline int is_final_url_char(unsigned char *curChar, unsigned char *endChar){
- if(is_whitespace(*curChar)){
- return 1;
- }
- else if(next_char_is_whitespace(curChar, endChar)) {
- // next char is whitespace so this char could be the final char in the url
- return char_disallowed_at_end_url(*curChar);
- }
- else{
- // next char isn't whitespace so it can't be a final char
- return 0;
- }
-}
-
-static inline int is_underscore(int c) {
+static inline int is_underscore(char c) {
return c == '_';
}
@@ -549,7 +522,7 @@ static inline int parse_utf8_char(struct cursor *cursor, unsigned int *code_poin
remaining_bytes = 0;
*utf8_length = 1; // Assume 1 byte length for unrecognized UTF-8 characters
// TODO: We need to gracefully handle unrecognized UTF-8 characters
- printf("Invalid UTF-8 byte: %x\n", *code_point);
+ //printf("Invalid UTF-8 byte: %x\n", *code_point);
*code_point = ((first_byte & 0xF0) << 6); // Prevent testing as punctuation
return 0; // Invalid first byte
}
@@ -660,7 +633,7 @@ static inline int consume_until_boundary(struct cursor *cur) {
if (!parse_utf8_char(cur, &c, utf8_char_length)) {
if (!is_right_boundary(c)){
// TODO: We should work towards handling all UTF-8 characters.
- printf("Invalid UTF-8 code point: %x\n", c);
+ //printf("Invalid UTF-8 code point: %x\n", c);
}
}
}
@@ -695,23 +668,6 @@ static inline int consume_until_whitespace(struct cursor *cur, int or_end) {
return or_end;
}
-static inline int consume_until_end_url(struct cursor *cur, int or_end) {
- char c;
- int consumedAtLeastOne = 0;
-
- while (cur->p < cur->end) {
- c = *cur->p;
-
- if (is_final_url_char(cur->p, cur->end))
- return consumedAtLeastOne;
-
- cur->p++;
- consumedAtLeastOne = 1;
- }
-
- return or_end;
-}
-
static inline int consume_until_non_alphanumeric(struct cursor *cur, int or_end) {
char c;
int consumedAtLeastOne = 0;
@@ -741,5 +697,13 @@ static inline int cursor_memset(struct cursor *cursor, unsigned char c, int n)
return 1;
}
+static void consume_whitespace_or_punctuation(struct cursor *cur)
+{
+ while (cur->p < cur->end) {
+ if (!is_right_boundary(*cur->p))
+ return;
+ cur->p++;
+ }
+}
#endif