nostrdb: move everything to src
Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
committed by
Daniel D’Aquino
parent
1fb88a912a
commit
1ffbd80c67
0
nostrdb/src/bindings/c/.dir
Normal file
0
nostrdb/src/bindings/c/.dir
Normal file
685
nostrdb/src/bindings/c/flatbuffers_common_builder.h
Normal file
685
nostrdb/src/bindings/c/flatbuffers_common_builder.h
Normal file
@@ -0,0 +1,685 @@
|
||||
#ifndef FLATBUFFERS_COMMON_BUILDER_H
|
||||
#define FLATBUFFERS_COMMON_BUILDER_H
|
||||
|
||||
/* Generated by flatcc 0.6.1 FlatBuffers schema compiler for C by dvide.com */
|
||||
|
||||
/* Common FlatBuffers build functionality for C. */
|
||||
|
||||
#include "flatcc/flatcc_prologue.h"
|
||||
#ifndef FLATBUILDER_H
|
||||
#include "flatcc/flatcc_builder.h"
|
||||
#endif
|
||||
typedef flatcc_builder_t flatbuffers_builder_t;
|
||||
typedef flatcc_builder_ref_t flatbuffers_ref_t;
|
||||
typedef flatcc_builder_ref_t flatbuffers_vec_ref_t;
|
||||
typedef flatcc_builder_union_ref_t flatbuffers_union_ref_t;
|
||||
typedef flatcc_builder_union_vec_ref_t flatbuffers_union_vec_ref_t;
|
||||
/* integer return code (ref and ptr always fail on 0) */
|
||||
#define flatbuffers_failed(x) ((x) < 0)
|
||||
typedef flatbuffers_ref_t flatbuffers_root_t;
|
||||
#define flatbuffers_root(ref) ((flatbuffers_root_t)(ref))
|
||||
|
||||
#define __flatbuffers_memoize_begin(B, src)\
|
||||
do { flatcc_builder_ref_t _ref; if ((_ref = flatcc_builder_refmap_find((B), (src)))) return _ref; } while (0)
|
||||
#define __flatbuffers_memoize_end(B, src, op) do { return flatcc_builder_refmap_insert((B), (src), (op)); } while (0)
|
||||
#define __flatbuffers_memoize(B, src, op) do { __flatbuffers_memoize_begin(B, src); __flatbuffers_memoize_end(B, src, op); } while (0)
|
||||
|
||||
#define __flatbuffers_build_buffer(NS)\
|
||||
typedef NS ## ref_t NS ## buffer_ref_t;\
|
||||
static inline int NS ## buffer_start(NS ## builder_t *B, const NS ##fid_t fid)\
|
||||
{ return flatcc_builder_start_buffer(B, fid, 0, 0); }\
|
||||
static inline int NS ## buffer_start_with_size(NS ## builder_t *B, const NS ##fid_t fid)\
|
||||
{ return flatcc_builder_start_buffer(B, fid, 0, flatcc_builder_with_size); }\
|
||||
static inline int NS ## buffer_start_aligned(NS ## builder_t *B, NS ##fid_t fid, uint16_t block_align)\
|
||||
{ return flatcc_builder_start_buffer(B, fid, block_align, 0); }\
|
||||
static inline int NS ## buffer_start_aligned_with_size(NS ## builder_t *B, NS ##fid_t fid, uint16_t block_align)\
|
||||
{ return flatcc_builder_start_buffer(B, fid, block_align, flatcc_builder_with_size); }\
|
||||
static inline NS ## buffer_ref_t NS ## buffer_end(NS ## builder_t *B, NS ## ref_t root)\
|
||||
{ return flatcc_builder_end_buffer(B, root); }
|
||||
|
||||
#define __flatbuffers_build_table_root(NS, N, FID, TFID)\
|
||||
static inline int N ## _start_as_root(NS ## builder_t *B)\
|
||||
{ return NS ## buffer_start(B, FID) ? -1 : N ## _start(B); }\
|
||||
static inline int N ## _start_as_root_with_size(NS ## builder_t *B)\
|
||||
{ return NS ## buffer_start_with_size(B, FID) ? -1 : N ## _start(B); }\
|
||||
static inline int N ## _start_as_typed_root(NS ## builder_t *B)\
|
||||
{ return NS ## buffer_start(B, TFID) ? -1 : N ## _start(B); }\
|
||||
static inline int N ## _start_as_typed_root_with_size(NS ## builder_t *B)\
|
||||
{ return NS ## buffer_start_with_size(B, TFID) ? -1 : N ## _start(B); }\
|
||||
static inline NS ## buffer_ref_t N ## _end_as_root(NS ## builder_t *B)\
|
||||
{ return NS ## buffer_end(B, N ## _end(B)); }\
|
||||
static inline NS ## buffer_ref_t N ## _end_as_typed_root(NS ## builder_t *B)\
|
||||
{ return NS ## buffer_end(B, N ## _end(B)); }\
|
||||
static inline NS ## buffer_ref_t N ## _create_as_root(NS ## builder_t *B __ ## N ## _formal_args)\
|
||||
{ if (NS ## buffer_start(B, FID)) return 0; return NS ## buffer_end(B, N ## _create(B __ ## N ## _call_args)); }\
|
||||
static inline NS ## buffer_ref_t N ## _create_as_root_with_size(NS ## builder_t *B __ ## N ## _formal_args)\
|
||||
{ if (NS ## buffer_start_with_size(B, FID)) return 0; return NS ## buffer_end(B, N ## _create(B __ ## N ## _call_args)); }\
|
||||
static inline NS ## buffer_ref_t N ## _create_as_typed_root(NS ## builder_t *B __ ## N ## _formal_args)\
|
||||
{ if (NS ## buffer_start(B, TFID)) return 0; return NS ## buffer_end(B, N ## _create(B __ ## N ## _call_args)); }\
|
||||
static inline NS ## buffer_ref_t N ## _create_as_typed_root_with_size(NS ## builder_t *B __ ## N ## _formal_args)\
|
||||
{ if (NS ## buffer_start_with_size(B, TFID)) return 0; return NS ## buffer_end(B, N ## _create(B __ ## N ## _call_args)); }\
|
||||
static inline NS ## buffer_ref_t N ## _clone_as_root(NS ## builder_t *B, N ## _table_t t)\
|
||||
{ if (NS ## buffer_start(B, FID)) return 0; return NS ## buffer_end(B, N ## _clone(B, t)); }\
|
||||
static inline NS ## buffer_ref_t N ## _clone_as_root_with_size(NS ## builder_t *B, N ## _table_t t)\
|
||||
{ if (NS ## buffer_start_with_size(B, FID)) return 0; return NS ## buffer_end(B, N ## _clone(B, t)); }\
|
||||
static inline NS ## buffer_ref_t N ## _clone_as_typed_root(NS ## builder_t *B, N ## _table_t t)\
|
||||
{ if (NS ## buffer_start(B, TFID)) return 0;return NS ## buffer_end(B, N ## _clone(B, t)); }\
|
||||
static inline NS ## buffer_ref_t N ## _clone_as_typed_root_with_size(NS ## builder_t *B, N ## _table_t t)\
|
||||
{ if (NS ## buffer_start_with_size(B, TFID)) return 0; return NS ## buffer_end(B, N ## _clone(B, t)); }
|
||||
|
||||
#define __flatbuffers_build_table_prolog(NS, N, FID, TFID)\
|
||||
__flatbuffers_build_table_vector_ops(NS, N ## _vec, N)\
|
||||
__flatbuffers_build_table_root(NS, N, FID, TFID)
|
||||
|
||||
#define __flatbuffers_build_struct_root(NS, N, A, FID, TFID)\
|
||||
static inline N ## _t *N ## _start_as_root(NS ## builder_t *B)\
|
||||
{ return NS ## buffer_start(B, FID) ? 0 : N ## _start(B); }\
|
||||
static inline N ## _t *N ## _start_as_root_with_size(NS ## builder_t *B)\
|
||||
{ return NS ## buffer_start_with_size(B, FID) ? 0 : N ## _start(B); }\
|
||||
static inline N ## _t *N ## _start_as_typed_root(NS ## builder_t *B)\
|
||||
{ return NS ## buffer_start(B, TFID) ? 0 : N ## _start(B); }\
|
||||
static inline N ## _t *N ## _start_as_typed_root_with_size(NS ## builder_t *B)\
|
||||
{ return NS ## buffer_start_with_size(B, TFID) ? 0 : N ## _start(B); }\
|
||||
static inline NS ## buffer_ref_t N ## _end_as_root(NS ## builder_t *B)\
|
||||
{ return NS ## buffer_end(B, N ## _end(B)); }\
|
||||
static inline NS ## buffer_ref_t N ## _end_as_typed_root(NS ## builder_t *B)\
|
||||
{ return NS ## buffer_end(B, N ## _end(B)); }\
|
||||
static inline NS ## buffer_ref_t N ## _end_pe_as_root(NS ## builder_t *B)\
|
||||
{ return NS ## buffer_end(B, N ## _end_pe(B)); }\
|
||||
static inline NS ## buffer_ref_t N ## _end_pe_as_typed_root(NS ## builder_t *B)\
|
||||
{ return NS ## buffer_end(B, N ## _end_pe(B)); }\
|
||||
static inline NS ## buffer_ref_t N ## _create_as_root(NS ## builder_t *B __ ## N ## _formal_args)\
|
||||
{ return flatcc_builder_create_buffer(B, FID, 0,\
|
||||
N ## _create(B __ ## N ## _call_args), A, 0); }\
|
||||
static inline NS ## buffer_ref_t N ## _create_as_root_with_size(NS ## builder_t *B __ ## N ## _formal_args)\
|
||||
{ return flatcc_builder_create_buffer(B, FID, 0,\
|
||||
N ## _create(B __ ## N ## _call_args), A, flatcc_builder_with_size); }\
|
||||
static inline NS ## buffer_ref_t N ## _create_as_typed_root(NS ## builder_t *B __ ## N ## _formal_args)\
|
||||
{ return flatcc_builder_create_buffer(B, TFID, 0,\
|
||||
N ## _create(B __ ## N ## _call_args), A, 0); }\
|
||||
static inline NS ## buffer_ref_t N ## _create_as_typed_root_with_size(NS ## builder_t *B __ ## N ## _formal_args)\
|
||||
{ return flatcc_builder_create_buffer(B, TFID, 0,\
|
||||
N ## _create(B __ ## N ## _call_args), A, flatcc_builder_with_size); }\
|
||||
static inline NS ## buffer_ref_t N ## _clone_as_root(NS ## builder_t *B, N ## _struct_t p)\
|
||||
{ return flatcc_builder_create_buffer(B, FID, 0, N ## _clone(B, p), A, 0); }\
|
||||
static inline NS ## buffer_ref_t N ## _clone_as_root_with_size(NS ## builder_t *B, N ## _struct_t p)\
|
||||
{ return flatcc_builder_create_buffer(B, FID, 0, N ## _clone(B, p), A, flatcc_builder_with_size); }\
|
||||
static inline NS ## buffer_ref_t N ## _clone_as_typed_root(NS ## builder_t *B, N ## _struct_t p)\
|
||||
{ return flatcc_builder_create_buffer(B, TFID, 0, N ## _clone(B, p), A, 0); }\
|
||||
static inline NS ## buffer_ref_t N ## _clone_as_typed_root_with_size(NS ## builder_t *B, N ## _struct_t p)\
|
||||
{ return flatcc_builder_create_buffer(B, TFID, 0, N ## _clone(B, p), A, flatcc_builder_with_size); }
|
||||
|
||||
#define __flatbuffers_build_nested_table_root(NS, N, TN, FID, TFID)\
|
||||
static inline int N ## _start_as_root(NS ## builder_t *B)\
|
||||
{ return NS ## buffer_start(B, FID) ? -1 : TN ## _start(B); }\
|
||||
static inline int N ## _start_as_typed_root(NS ## builder_t *B)\
|
||||
{ return NS ## buffer_start(B, TFID) ? -1 : TN ## _start(B); }\
|
||||
static inline int N ## _end_as_root(NS ## builder_t *B)\
|
||||
{ return N ## _add(B, NS ## buffer_end(B, TN ## _end(B))); }\
|
||||
static inline int N ## _end_as_typed_root(NS ## builder_t *B)\
|
||||
{ return N ## _add(B, NS ## buffer_end(B, TN ## _end(B))); }\
|
||||
static inline int N ## _nest(NS ## builder_t *B, void *data, size_t size, uint16_t align)\
|
||||
{ return N ## _add(B, flatcc_builder_create_vector(B, data, size, 1,\
|
||||
align ? align : 8, FLATBUFFERS_COUNT_MAX(1))); }\
|
||||
static inline int N ## _typed_nest(NS ## builder_t *B, void *data, size_t size, uint16_t align)\
|
||||
{ return N ## _add(B, flatcc_builder_create_vector(B, data, size, 1,\
|
||||
align ? align : 8, FLATBUFFERS_COUNT_MAX(1))); }\
|
||||
static inline int N ## _clone_as_root(NS ## builder_t *B, TN ## _table_t t)\
|
||||
{ return N ## _add(B, TN ## _clone_as_root(B, t)); }\
|
||||
static inline int N ## _clone_as_typed_root(NS ## builder_t *B, TN ## _table_t t)\
|
||||
{ return N ## _add(B, TN ## _clone_as_typed_root(B, t)); }
|
||||
|
||||
#define __flatbuffers_build_nested_struct_root(NS, N, TN, A, FID, TFID)\
|
||||
static inline TN ## _t *N ## _start_as_root(NS ## builder_t *B)\
|
||||
{ return NS ## buffer_start(B, FID) ? 0 : TN ## _start(B); }\
|
||||
static inline TN ## _t *N ## _start_as_typed_root(NS ## builder_t *B)\
|
||||
{ return NS ## buffer_start(B, FID) ? 0 : TN ## _start(B); }\
|
||||
static inline int N ## _end_as_root(NS ## builder_t *B)\
|
||||
{ return N ## _add(B, NS ## buffer_end(B, TN ## _end(B))); }\
|
||||
static inline int N ## _end_as_typed_root(NS ## builder_t *B)\
|
||||
{ return N ## _add(B, NS ## buffer_end(B, TN ## _end(B))); }\
|
||||
static inline int N ## _end_pe_as_root(NS ## builder_t *B)\
|
||||
{ return N ## _add(B, NS ## buffer_end(B, TN ## _end_pe(B))); }\
|
||||
static inline int N ## _create_as_root(NS ## builder_t *B __ ## TN ## _formal_args)\
|
||||
{ return N ## _add(B, flatcc_builder_create_buffer(B, FID, 0,\
|
||||
TN ## _create(B __ ## TN ## _call_args), A, flatcc_builder_is_nested)); }\
|
||||
static inline int N ## _create_as_typed_root(NS ## builder_t *B __ ## TN ## _formal_args)\
|
||||
{ return N ## _add(B, flatcc_builder_create_buffer(B, TFID, 0,\
|
||||
TN ## _create(B __ ## TN ## _call_args), A, flatcc_builder_is_nested)); }\
|
||||
static inline int N ## _nest(NS ## builder_t *B, void *data, size_t size, uint16_t align)\
|
||||
{ return N ## _add(B, flatcc_builder_create_vector(B, data, size, 1,\
|
||||
align < A ? A : align, FLATBUFFERS_COUNT_MAX(1))); }\
|
||||
static inline int N ## _typed_nest(NS ## builder_t *B, void *data, size_t size, uint16_t align)\
|
||||
{ return N ## _add(B, flatcc_builder_create_vector(B, data, size, 1,\
|
||||
align < A ? A : align, FLATBUFFERS_COUNT_MAX(1))); }\
|
||||
static inline int N ## _clone_as_root(NS ## builder_t *B, TN ## _struct_t p)\
|
||||
{ return N ## _add(B, TN ## _clone_as_root(B, p)); }\
|
||||
static inline int N ## _clone_as_typed_root(NS ## builder_t *B, TN ## _struct_t p)\
|
||||
{ return N ## _add(B, TN ## _clone_as_typed_root(B, p)); }
|
||||
|
||||
#define __flatbuffers_build_vector_ops(NS, V, N, TN, T)\
|
||||
static inline T *V ## _extend(NS ## builder_t *B, size_t len)\
|
||||
{ return (T *)flatcc_builder_extend_vector(B, len); }\
|
||||
static inline T *V ## _append(NS ## builder_t *B, const T *data, size_t len)\
|
||||
{ return (T *)flatcc_builder_append_vector(B, data, len); }\
|
||||
static inline int V ## _truncate(NS ## builder_t *B, size_t len)\
|
||||
{ return flatcc_builder_truncate_vector(B, len); }\
|
||||
static inline T *V ## _edit(NS ## builder_t *B)\
|
||||
{ return (T *)flatcc_builder_vector_edit(B); }\
|
||||
static inline size_t V ## _reserved_len(NS ## builder_t *B)\
|
||||
{ return flatcc_builder_vector_count(B); }\
|
||||
static inline T *V ## _push(NS ## builder_t *B, const T *p)\
|
||||
{ T *_p; return (_p = (T *)flatcc_builder_extend_vector(B, 1)) ? (memcpy(_p, p, TN ## __size()), _p) : 0; }\
|
||||
static inline T *V ## _push_copy(NS ## builder_t *B, const T *p)\
|
||||
{ T *_p; return (_p = (T *)flatcc_builder_extend_vector(B, 1)) ? TN ## _copy(_p, p) : 0; }\
|
||||
static inline T *V ## _push_clone(NS ## builder_t *B, const T *p)\
|
||||
{ T *_p; return (_p = (T *)flatcc_builder_extend_vector(B, 1)) ? TN ## _copy(_p, p) : 0; }\
|
||||
static inline T *V ## _push_create(NS ## builder_t *B __ ## TN ## _formal_args)\
|
||||
{ T *_p; return (_p = (T *)flatcc_builder_extend_vector(B, 1)) ? TN ## _assign(_p __ ## TN ## _call_args) : 0; }
|
||||
|
||||
#define __flatbuffers_build_vector(NS, N, T, S, A)\
|
||||
typedef NS ## ref_t N ## _vec_ref_t;\
|
||||
static inline int N ## _vec_start(NS ## builder_t *B)\
|
||||
{ return flatcc_builder_start_vector(B, S, A, FLATBUFFERS_COUNT_MAX(S)); }\
|
||||
static inline N ## _vec_ref_t N ## _vec_end_pe(NS ## builder_t *B)\
|
||||
{ return flatcc_builder_end_vector(B); }\
|
||||
static inline N ## _vec_ref_t N ## _vec_end(NS ## builder_t *B)\
|
||||
{ if (!NS ## is_native_pe()) { size_t i, n; T *p = (T *)flatcc_builder_vector_edit(B);\
|
||||
for (i = 0, n = flatcc_builder_vector_count(B); i < n; ++i)\
|
||||
{ N ## _to_pe(N ## __ptr_add(p, i)); }} return flatcc_builder_end_vector(B); }\
|
||||
static inline N ## _vec_ref_t N ## _vec_create_pe(NS ## builder_t *B, const T *data, size_t len)\
|
||||
{ return flatcc_builder_create_vector(B, data, len, S, A, FLATBUFFERS_COUNT_MAX(S)); }\
|
||||
static inline N ## _vec_ref_t N ## _vec_create(NS ## builder_t *B, const T *data, size_t len)\
|
||||
{ if (!NS ## is_native_pe()) { size_t i; T *p; int ret = flatcc_builder_start_vector(B, S, A, FLATBUFFERS_COUNT_MAX(S)); if (ret) { return ret; }\
|
||||
p = (T *)flatcc_builder_extend_vector(B, len); if (!p) return 0;\
|
||||
for (i = 0; i < len; ++i) { N ## _copy_to_pe(N ## __ptr_add(p, i), N ## __const_ptr_add(data, i)); }\
|
||||
return flatcc_builder_end_vector(B); } else return flatcc_builder_create_vector(B, data, len, S, A, FLATBUFFERS_COUNT_MAX(S)); }\
|
||||
static inline N ## _vec_ref_t N ## _vec_clone(NS ## builder_t *B, N ##_vec_t vec)\
|
||||
{ __flatbuffers_memoize(B, vec, flatcc_builder_create_vector(B, vec, N ## _vec_len(vec), S, A, FLATBUFFERS_COUNT_MAX(S))); }\
|
||||
static inline N ## _vec_ref_t N ## _vec_slice(NS ## builder_t *B, N ##_vec_t vec, size_t index, size_t len)\
|
||||
{ size_t n = N ## _vec_len(vec); if (index >= n) index = n; n -= index; if (len > n) len = n;\
|
||||
return flatcc_builder_create_vector(B, N ## __const_ptr_add(vec, index), len, S, A, FLATBUFFERS_COUNT_MAX(S)); }\
|
||||
__flatbuffers_build_vector_ops(NS, N ## _vec, N, N, T)
|
||||
|
||||
#define __flatbuffers_build_union_vector_ops(NS, V, N, TN)\
|
||||
static inline TN ## _union_ref_t *V ## _extend(NS ## builder_t *B, size_t len)\
|
||||
{ return flatcc_builder_extend_union_vector(B, len); }\
|
||||
static inline TN ## _union_ref_t *V ## _append(NS ## builder_t *B, const TN ## _union_ref_t *data, size_t len)\
|
||||
{ return flatcc_builder_append_union_vector(B, data, len); }\
|
||||
static inline int V ## _truncate(NS ## builder_t *B, size_t len)\
|
||||
{ return flatcc_builder_truncate_union_vector(B, len); }\
|
||||
static inline TN ## _union_ref_t *V ## _edit(NS ## builder_t *B)\
|
||||
{ return (TN ## _union_ref_t *) flatcc_builder_union_vector_edit(B); }\
|
||||
static inline size_t V ## _reserved_len(NS ## builder_t *B)\
|
||||
{ return flatcc_builder_union_vector_count(B); }\
|
||||
static inline TN ## _union_ref_t *V ## _push(NS ## builder_t *B, const TN ## _union_ref_t ref)\
|
||||
{ return flatcc_builder_union_vector_push(B, ref); }\
|
||||
static inline TN ## _union_ref_t *V ## _push_clone(NS ## builder_t *B, TN ## _union_t u)\
|
||||
{ return TN ## _vec_push(B, TN ## _clone(B, u)); }
|
||||
|
||||
#define __flatbuffers_build_union_vector(NS, N)\
|
||||
static inline int N ## _vec_start(NS ## builder_t *B)\
|
||||
{ return flatcc_builder_start_union_vector(B); }\
|
||||
static inline N ## _union_vec_ref_t N ## _vec_end(NS ## builder_t *B)\
|
||||
{ return flatcc_builder_end_union_vector(B); }\
|
||||
static inline N ## _union_vec_ref_t N ## _vec_create(NS ## builder_t *B, const N ## _union_ref_t *data, size_t len)\
|
||||
{ return flatcc_builder_create_union_vector(B, data, len); }\
|
||||
__flatbuffers_build_union_vector_ops(NS, N ## _vec, N, N)\
|
||||
/* Preserves DAG structure separately for type and value vector, so a type vector could be shared for many value vectors. */\
|
||||
static inline N ## _union_vec_ref_t N ## _vec_clone(NS ## builder_t *B, N ##_union_vec_t vec)\
|
||||
{ N ## _union_vec_ref_t _uvref, _ret = { 0, 0 }; NS ## union_ref_t _uref; size_t _i, _len;\
|
||||
if (vec.type == 0) return _ret;\
|
||||
_uvref.type = flatcc_builder_refmap_find(B, vec.type); _uvref.value = flatcc_builder_refmap_find(B, vec.value);\
|
||||
_len = N ## _union_vec_len(vec); if (_uvref.type == 0) {\
|
||||
_uvref.type = flatcc_builder_refmap_insert(B, vec.type, (flatcc_builder_create_type_vector(B, vec.type, _len))); }\
|
||||
if (_uvref.type == 0) return _ret; if (_uvref.value == 0) {\
|
||||
if (flatcc_builder_start_offset_vector(B)) return _ret;\
|
||||
for (_i = 0; _i < _len; ++_i) { _uref = N ## _clone(B, N ## _union_vec_at(vec, _i));\
|
||||
if (!_uref.value || !(flatcc_builder_offset_vector_push(B, _uref.value))) return _ret; }\
|
||||
_uvref.value = flatcc_builder_refmap_insert(B, vec.value, flatcc_builder_end_offset_vector(B));\
|
||||
if (_uvref.value == 0) return _ret; } return _uvref; }
|
||||
|
||||
#define __flatbuffers_build_string_vector_ops(NS, N)\
|
||||
static inline int N ## _push_start(NS ## builder_t *B)\
|
||||
{ return NS ## string_start(B); }\
|
||||
static inline NS ## string_ref_t *N ## _push_end(NS ## builder_t *B)\
|
||||
{ return NS ## string_vec_push(B, NS ## string_end(B)); }\
|
||||
static inline NS ## string_ref_t *N ## _push_create(NS ## builder_t *B, const char *s, size_t len)\
|
||||
{ return NS ## string_vec_push(B, NS ## string_create(B, s, len)); }\
|
||||
static inline NS ## string_ref_t *N ## _push_create_str(NS ## builder_t *B, const char *s)\
|
||||
{ return NS ## string_vec_push(B, NS ## string_create_str(B, s)); }\
|
||||
static inline NS ## string_ref_t *N ## _push_create_strn(NS ## builder_t *B, const char *s, size_t max_len)\
|
||||
{ return NS ## string_vec_push(B, NS ## string_create_strn(B, s, max_len)); }\
|
||||
static inline NS ## string_ref_t *N ## _push_clone(NS ## builder_t *B, NS ## string_t string)\
|
||||
{ return NS ## string_vec_push(B, NS ## string_clone(B, string)); }\
|
||||
static inline NS ## string_ref_t *N ## _push_slice(NS ## builder_t *B, NS ## string_t string, size_t index, size_t len)\
|
||||
{ return NS ## string_vec_push(B, NS ## string_slice(B, string, index, len)); }
|
||||
|
||||
#define __flatbuffers_build_table_vector_ops(NS, N, TN)\
|
||||
static inline int N ## _push_start(NS ## builder_t *B)\
|
||||
{ return TN ## _start(B); }\
|
||||
static inline TN ## _ref_t *N ## _push_end(NS ## builder_t *B)\
|
||||
{ return N ## _push(B, TN ## _end(B)); }\
|
||||
static inline TN ## _ref_t *N ## _push_create(NS ## builder_t *B __ ## TN ##_formal_args)\
|
||||
{ return N ## _push(B, TN ## _create(B __ ## TN ## _call_args)); }
|
||||
|
||||
#define __flatbuffers_build_offset_vector_ops(NS, V, N, TN)\
|
||||
static inline TN ## _ref_t *V ## _extend(NS ## builder_t *B, size_t len)\
|
||||
{ return flatcc_builder_extend_offset_vector(B, len); }\
|
||||
static inline TN ## _ref_t *V ## _append(NS ## builder_t *B, const TN ## _ref_t *data, size_t len)\
|
||||
{ return flatcc_builder_append_offset_vector(B, data, len); }\
|
||||
static inline int V ## _truncate(NS ## builder_t *B, size_t len)\
|
||||
{ return flatcc_builder_truncate_offset_vector(B, len); }\
|
||||
static inline TN ## _ref_t *V ## _edit(NS ## builder_t *B)\
|
||||
{ return (TN ## _ref_t *)flatcc_builder_offset_vector_edit(B); }\
|
||||
static inline size_t V ## _reserved_len(NS ## builder_t *B)\
|
||||
{ return flatcc_builder_offset_vector_count(B); }\
|
||||
static inline TN ## _ref_t *V ## _push(NS ## builder_t *B, const TN ## _ref_t ref)\
|
||||
{ return ref ? flatcc_builder_offset_vector_push(B, ref) : 0; }
|
||||
|
||||
#define __flatbuffers_build_offset_vector(NS, N)\
|
||||
typedef NS ## ref_t N ## _vec_ref_t;\
|
||||
static inline int N ## _vec_start(NS ## builder_t *B)\
|
||||
{ return flatcc_builder_start_offset_vector(B); }\
|
||||
static inline N ## _vec_ref_t N ## _vec_end(NS ## builder_t *B)\
|
||||
{ return flatcc_builder_end_offset_vector(B); }\
|
||||
static inline N ## _vec_ref_t N ## _vec_create(NS ## builder_t *B, const N ## _ref_t *data, size_t len)\
|
||||
{ return flatcc_builder_create_offset_vector(B, data, len); }\
|
||||
__flatbuffers_build_offset_vector_ops(NS, N ## _vec, N, N)\
|
||||
static inline N ## _vec_ref_t N ## _vec_clone(NS ## builder_t *B, N ##_vec_t vec)\
|
||||
{ int _ret; N ## _ref_t _e; size_t _i, _len; __flatbuffers_memoize_begin(B, vec);\
|
||||
_len = N ## _vec_len(vec); if (flatcc_builder_start_offset_vector(B)) return 0;\
|
||||
for (_i = 0; _i < _len; ++_i) { if (!(_e = N ## _clone(B, N ## _vec_at(vec, _i)))) return 0;\
|
||||
if (!flatcc_builder_offset_vector_push(B, _e)) return 0; }\
|
||||
__flatbuffers_memoize_end(B, vec, flatcc_builder_end_offset_vector(B)); }\
|
||||
|
||||
#define __flatbuffers_build_string_ops(NS, N)\
|
||||
static inline char *N ## _append(NS ## builder_t *B, const char *s, size_t len)\
|
||||
{ return flatcc_builder_append_string(B, s, len); }\
|
||||
static inline char *N ## _append_str(NS ## builder_t *B, const char *s)\
|
||||
{ return flatcc_builder_append_string_str(B, s); }\
|
||||
static inline char *N ## _append_strn(NS ## builder_t *B, const char *s, size_t len)\
|
||||
{ return flatcc_builder_append_string_strn(B, s, len); }\
|
||||
static inline size_t N ## _reserved_len(NS ## builder_t *B)\
|
||||
{ return flatcc_builder_string_len(B); }\
|
||||
static inline char *N ## _extend(NS ## builder_t *B, size_t len)\
|
||||
{ return flatcc_builder_extend_string(B, len); }\
|
||||
static inline char *N ## _edit(NS ## builder_t *B)\
|
||||
{ return flatcc_builder_string_edit(B); }\
|
||||
static inline int N ## _truncate(NS ## builder_t *B, size_t len)\
|
||||
{ return flatcc_builder_truncate_string(B, len); }
|
||||
|
||||
#define __flatbuffers_build_string(NS)\
|
||||
typedef NS ## ref_t NS ## string_ref_t;\
|
||||
static inline int NS ## string_start(NS ## builder_t *B)\
|
||||
{ return flatcc_builder_start_string(B); }\
|
||||
static inline NS ## string_ref_t NS ## string_end(NS ## builder_t *B)\
|
||||
{ return flatcc_builder_end_string(B); }\
|
||||
static inline NS ## ref_t NS ## string_create(NS ## builder_t *B, const char *s, size_t len)\
|
||||
{ return flatcc_builder_create_string(B, s, len); }\
|
||||
static inline NS ## ref_t NS ## string_create_str(NS ## builder_t *B, const char *s)\
|
||||
{ return flatcc_builder_create_string_str(B, s); }\
|
||||
static inline NS ## ref_t NS ## string_create_strn(NS ## builder_t *B, const char *s, size_t len)\
|
||||
{ return flatcc_builder_create_string_strn(B, s, len); }\
|
||||
static inline NS ## string_ref_t NS ## string_clone(NS ## builder_t *B, NS ## string_t string)\
|
||||
{ __flatbuffers_memoize(B, string, flatcc_builder_create_string(B, string, NS ## string_len(string))); }\
|
||||
static inline NS ## string_ref_t NS ## string_slice(NS ## builder_t *B, NS ## string_t string, size_t index, size_t len)\
|
||||
{ size_t n = NS ## string_len(string); if (index >= n) index = n; n -= index; if (len > n) len = n;\
|
||||
return flatcc_builder_create_string(B, string + index, len); }\
|
||||
__flatbuffers_build_string_ops(NS, NS ## string)\
|
||||
__flatbuffers_build_offset_vector(NS, NS ## string)
|
||||
|
||||
#define __flatbuffers_copy_from_pe(P, P2, N) (*(P) = N ## _read_from_pe(P2), (P))
|
||||
#define __flatbuffers_from_pe(P, N) (*(P) = N ## _read_from_pe(P), (P))
|
||||
#define __flatbuffers_copy_to_pe(P, P2, N) (N ## _write_to_pe((P), *(P2)), (P))
|
||||
#define __flatbuffers_to_pe(P, N) (N ## _write_to_pe((P), *(P)), (P))
|
||||
#define __flatbuffers_define_fixed_array_primitives(NS, N, T)\
|
||||
static inline T *N ## _array_copy(T *p, const T *p2, size_t n)\
|
||||
{ memcpy(p, p2, n * sizeof(T)); return p; }\
|
||||
static inline T *N ## _array_copy_from_pe(T *p, const T *p2, size_t n)\
|
||||
{ size_t i; if (NS ## is_native_pe()) memcpy(p, p2, n * sizeof(T)); else\
|
||||
for (i = 0; i < n; ++i) N ## _copy_from_pe(&p[i], &p2[i]); return p; }\
|
||||
static inline T *N ## _array_copy_to_pe(T *p, const T *p2, size_t n)\
|
||||
{ size_t i; if (NS ## is_native_pe()) memcpy(p, p2, n * sizeof(T)); else\
|
||||
for (i = 0; i < n; ++i) N ## _copy_to_pe(&p[i], &p2[i]); return p; }
|
||||
#define __flatbuffers_define_scalar_primitives(NS, N, T)\
|
||||
static inline T *N ## _from_pe(T *p) { return __ ## NS ## from_pe(p, N); }\
|
||||
static inline T *N ## _to_pe(T *p) { return __ ## NS ## to_pe(p, N); }\
|
||||
static inline T *N ## _copy(T *p, const T *p2) { *p = *p2; return p; }\
|
||||
static inline T *N ## _copy_from_pe(T *p, const T *p2)\
|
||||
{ return __ ## NS ## copy_from_pe(p, p2, N); }\
|
||||
static inline T *N ## _copy_to_pe(T *p, const T *p2) \
|
||||
{ return __ ## NS ## copy_to_pe(p, p2, N); }\
|
||||
static inline T *N ## _assign(T *p, const T v0) { *p = v0; return p; }\
|
||||
static inline T *N ## _assign_from_pe(T *p, T v0)\
|
||||
{ *p = N ## _read_from_pe(&v0); return p; }\
|
||||
static inline T *N ## _assign_to_pe(T *p, T v0)\
|
||||
{ N ## _write_to_pe(p, v0); return p; }
|
||||
#define __flatbuffers_build_scalar(NS, N, T)\
|
||||
__ ## NS ## define_scalar_primitives(NS, N, T)\
|
||||
__ ## NS ## define_fixed_array_primitives(NS, N, T)\
|
||||
__ ## NS ## build_vector(NS, N, T, sizeof(T), sizeof(T))
|
||||
/* Depends on generated copy_to/from_pe functions, and the type. */
|
||||
#define __flatbuffers_define_struct_primitives(NS, N)\
|
||||
static inline N ## _t *N ##_to_pe(N ## _t *p)\
|
||||
{ if (!NS ## is_native_pe()) { N ## _copy_to_pe(p, p); }; return p; }\
|
||||
static inline N ## _t *N ##_from_pe(N ## _t *p)\
|
||||
{ if (!NS ## is_native_pe()) { N ## _copy_from_pe(p, p); }; return p; }\
|
||||
static inline N ## _t *N ## _clear(N ## _t *p) { return (N ## _t *)memset(p, 0, N ## __size()); }
|
||||
|
||||
/* Depends on generated copy/assign_to/from_pe functions, and the type. */
|
||||
#define __flatbuffers_build_struct(NS, N, S, A, FID, TFID)\
|
||||
__ ## NS ## define_struct_primitives(NS, N)\
|
||||
typedef NS ## ref_t N ## _ref_t;\
|
||||
static inline N ## _t *N ## _start(NS ## builder_t *B)\
|
||||
{ return (N ## _t *)flatcc_builder_start_struct(B, S, A); }\
|
||||
static inline N ## _ref_t N ## _end(NS ## builder_t *B)\
|
||||
{ if (!NS ## is_native_pe()) { N ## _to_pe((N ## _t *)flatcc_builder_struct_edit(B)); }\
|
||||
return flatcc_builder_end_struct(B); }\
|
||||
static inline N ## _ref_t N ## _end_pe(NS ## builder_t *B)\
|
||||
{ return flatcc_builder_end_struct(B); }\
|
||||
static inline N ## _ref_t N ## _create(NS ## builder_t *B __ ## N ## _formal_args)\
|
||||
{ N ## _t *_p = N ## _start(B); if (!_p) return 0; N ##_assign_to_pe(_p __ ## N ## _call_args);\
|
||||
return N ## _end_pe(B); }\
|
||||
static inline N ## _ref_t N ## _clone(NS ## builder_t *B, N ## _struct_t p)\
|
||||
{ N ## _t *_p; __flatbuffers_memoize_begin(B, p); _p = N ## _start(B); if (!_p) return 0;\
|
||||
N ## _copy(_p, p); __flatbuffers_memoize_end(B, p, N ##_end_pe(B)); }\
|
||||
__flatbuffers_build_vector(NS, N, N ## _t, S, A)\
|
||||
__flatbuffers_build_struct_root(NS, N, A, FID, TFID)\
|
||||
|
||||
#define __flatbuffers_struct_clear_field(p) memset((p), 0, sizeof(*(p)))
|
||||
#define __flatbuffers_build_table(NS, N, K)\
|
||||
static inline int N ## _start(NS ## builder_t *B)\
|
||||
{ return flatcc_builder_start_table(B, K); }\
|
||||
static inline N ## _ref_t N ## _end(NS ## builder_t *B)\
|
||||
{ FLATCC_ASSERT(flatcc_builder_check_required(B, __ ## N ## _required,\
|
||||
sizeof(__ ## N ## _required) / sizeof(__ ## N ## _required[0]) - 1));\
|
||||
return flatcc_builder_end_table(B); }\
|
||||
__flatbuffers_build_offset_vector(NS, N)
|
||||
|
||||
#define __flatbuffers_build_table_field(ID, NS, N, TN, TT)\
|
||||
static inline int N ## _add(NS ## builder_t *B, TN ## _ref_t ref)\
|
||||
{ TN ## _ref_t *_p; return (ref && (_p = flatcc_builder_table_add_offset(B, ID))) ?\
|
||||
((*_p = ref), 0) : -1; }\
|
||||
static inline int N ## _start(NS ## builder_t *B)\
|
||||
{ return TN ## _start(B); }\
|
||||
static inline int N ## _end(NS ## builder_t *B)\
|
||||
{ return N ## _add(B, TN ## _end(B)); }\
|
||||
static inline TN ## _ref_t N ## _create(NS ## builder_t *B __ ## TN ##_formal_args)\
|
||||
{ return N ## _add(B, TN ## _create(B __ ## TN ## _call_args)); }\
|
||||
static inline int N ## _clone(NS ## builder_t *B, TN ## _table_t p)\
|
||||
{ return N ## _add(B, TN ## _clone(B, p)); }\
|
||||
static inline int N ## _pick(NS ## builder_t *B, TT ## _table_t t)\
|
||||
{ TN ## _table_t _p = N ## _get(t); return _p ? N ## _clone(B, _p) : 0; }
|
||||
|
||||
#define __flatbuffers_build_union_field(ID, NS, N, TN, TT)\
|
||||
static inline int N ## _add(NS ## builder_t *B, TN ## _union_ref_t uref)\
|
||||
{ NS ## ref_t *_p; TN ## _union_type_t *_pt; if (uref.type == TN ## _NONE) return 0; if (uref.value == 0) return -1;\
|
||||
if (!(_pt = (TN ## _union_type_t *)flatcc_builder_table_add(B, ID - 1, sizeof(*_pt), sizeof(*_pt)))) return -1;\
|
||||
*_pt = uref.type; if (!(_p = flatcc_builder_table_add_offset(B, ID))) return -1; *_p = uref.value; return 0; }\
|
||||
static inline int N ## _add_type(NS ## builder_t *B, TN ## _union_type_t type)\
|
||||
{ TN ## _union_type_t *_pt; if (type == TN ## _NONE) return 0; return (_pt = (TN ## _union_type_t *)flatcc_builder_table_add(B, ID - 1,\
|
||||
sizeof(*_pt), sizeof(*_pt))) ? ((*_pt = type), 0) : -1; }\
|
||||
static inline int N ## _add_value(NS ## builder_t *B, TN ## _union_ref_t uref)\
|
||||
{ NS ## ref_t *p; if (uref.type == TN ## _NONE) return 0; return (p = flatcc_builder_table_add_offset(B, ID)) ?\
|
||||
((*p = uref.value), 0) : -1; }\
|
||||
static inline int N ## _clone(NS ## builder_t *B, TN ## _union_t p)\
|
||||
{ return N ## _add(B, TN ## _clone(B, p)); }\
|
||||
static inline int N ## _pick(NS ## builder_t *B, TT ## _table_t t)\
|
||||
{ TN ## _union_t _p = N ## _union(t); return _p.type ? N ## _clone(B, _p) : 0; }
|
||||
|
||||
/* M is the union value name and T is its type, i.e. the qualified name. */
|
||||
#define __flatbuffers_build_union_table_value_field(NS, N, NU, M, T)\
|
||||
static inline int N ## _ ## M ## _add(NS ## builder_t *B, T ## _ref_t ref)\
|
||||
{ return N ## _add(B, NU ## _as_ ## M (ref)); }\
|
||||
static inline int N ## _ ## M ## _start(NS ## builder_t *B)\
|
||||
{ return T ## _start(B); }\
|
||||
static inline int N ## _ ## M ## _end(NS ## builder_t *B)\
|
||||
{ T ## _ref_t ref = T ## _end(B);\
|
||||
return ref ? N ## _ ## M ## _add(B, ref) : -1; }\
|
||||
static inline int N ## _ ## M ## _create(NS ## builder_t *B __ ## T ##_formal_args)\
|
||||
{ T ## _ref_t ref = T ## _create(B __ ## T ## _call_args);\
|
||||
return ref ? N ## _add(B, NU ## _as_ ## M(ref)) : -1; }\
|
||||
static inline int N ## _ ## M ## _clone(NS ## builder_t *B, T ## _table_t t)\
|
||||
{ T ## _ref_t ref = T ## _clone(B, t);\
|
||||
return ref ? N ## _add(B, NU ## _as_ ## M(ref)) : -1; }
|
||||
|
||||
/* M is the union value name and T is its type, i.e. the qualified name. */
|
||||
#define __flatbuffers_build_union_struct_value_field(NS, N, NU, M, T)\
|
||||
static inline int N ## _ ## M ## _add(NS ## builder_t *B, T ## _ref_t ref)\
|
||||
{ return N ## _add(B, NU ## _as_ ## M (ref)); }\
|
||||
static inline T ## _t *N ## _ ## M ## _start(NS ## builder_t *B)\
|
||||
{ return T ## _start(B); }\
|
||||
static inline int N ## _ ## M ## _end(NS ## builder_t *B)\
|
||||
{ T ## _ref_t ref = T ## _end(B);\
|
||||
return ref ? N ## _ ## M ## _add(B, ref) : -1; }\
|
||||
static inline int N ## _ ## M ## _create(NS ## builder_t *B __ ## T ##_formal_args)\
|
||||
{ T ## _ref_t ref = T ## _create(B __ ## T ## _call_args);\
|
||||
return ref ? N ## _add(B, NU ## _as_ ## M(ref)) : -1; }\
|
||||
static inline int N ## _ ## M ## _end_pe(NS ## builder_t *B)\
|
||||
{ T ## _ref_t ref = T ## _end_pe(B);\
|
||||
return ref ? N ## _add(B, NU ## _as_ ## M(ref)) : -1; }\
|
||||
static inline int N ## _ ## M ## _clone(NS ## builder_t *B, T ## _struct_t p)\
|
||||
{ T ## _ref_t ref = T ## _clone(B, p);\
|
||||
return ref ? N ## _add(B, NU ## _as_ ## M(ref)) : -1; }
|
||||
#define __flatbuffers_build_union_string_value_field(NS, N, NU, M)\
|
||||
static inline int N ## _ ## M ## _add(NS ## builder_t *B, NS ## string_ref_t ref)\
|
||||
{ return N ## _add(B, NU ## _as_ ## M (ref)); }\
|
||||
__flatbuffers_build_string_field_ops(NS, N ## _ ## M)
|
||||
|
||||
/* NS: common namespace, ID: table field id (not offset), TN: name of type T, TT: name of table type
|
||||
* S: sizeof of scalar type, A: alignment of type T, default value V of type T. */
|
||||
#define __flatbuffers_build_scalar_field(ID, NS, N, TN, T, S, A, V, TT)\
|
||||
static inline int N ## _add(NS ## builder_t *B, const T v)\
|
||||
{ T *_p; if (v == V) return 0; if (!(_p = (T *)flatcc_builder_table_add(B, ID, S, A))) return -1;\
|
||||
TN ## _assign_to_pe(_p, v); return 0; }\
|
||||
static inline int N ## _force_add(NS ## builder_t *B, const T v)\
|
||||
{ T *_p; if (!(_p = (T *)flatcc_builder_table_add(B, ID, S, A))) return -1;\
|
||||
TN ## _assign_to_pe(_p, v); return 0; }\
|
||||
/* Clone does not skip default values and expects pe endian content. */\
|
||||
static inline int N ## _clone(NS ## builder_t *B, const T *p)\
|
||||
{ return 0 == flatcc_builder_table_add_copy(B, ID, p, S, A) ? -1 : 0; }\
|
||||
/* Transferring a missing field is a nop success with 0 as result. */\
|
||||
static inline int N ## _pick(NS ## builder_t *B, TT ## _table_t t)\
|
||||
{ const T *_p = N ## _get_ptr(t); return _p ? N ## _clone(B, _p) : 0; }
|
||||
|
||||
/* NS: common namespace, ID: table field id (not offset), TN: name of type T, TT: name of table type
|
||||
* S: sizeof of scalar type, A: alignment of type T. */
|
||||
#define __flatbuffers_build_scalar_optional_field(ID, NS, N, TN, T, S, A, TT)\
|
||||
static inline int N ## _add(NS ## builder_t *B, const T v)\
|
||||
{ T *_p; if (!(_p = (T *)flatcc_builder_table_add(B, ID, S, A))) return -1;\
|
||||
TN ## _assign_to_pe(_p, v); return 0; }\
|
||||
/* Clone does not skip default values and expects pe endian content. */\
|
||||
static inline int N ## _clone(NS ## builder_t *B, const T *p)\
|
||||
{ return 0 == flatcc_builder_table_add_copy(B, ID, p, S, A) ? -1 : 0; }\
|
||||
/* Transferring a missing field is a nop success with 0 as result. */\
|
||||
static inline int N ## _pick(NS ## builder_t *B, TT ## _table_t t)\
|
||||
{ const T *_p = N ## _get_ptr(t); return _p ? N ## _clone(B, _p) : 0; }
|
||||
|
||||
#define __flatbuffers_build_struct_field(ID, NS, N, TN, S, A, TT)\
|
||||
static inline TN ## _t *N ## _start(NS ## builder_t *B)\
|
||||
{ return (TN ## _t *)flatcc_builder_table_add(B, ID, S, A); }\
|
||||
static inline int N ## _end(NS ## builder_t *B)\
|
||||
{ if (!NS ## is_native_pe()) { TN ## _to_pe((TN ## _t *)flatcc_builder_table_edit(B, S)); } return 0; }\
|
||||
static inline int N ## _end_pe(NS ## builder_t *B) { return 0; }\
|
||||
static inline int N ## _create(NS ## builder_t *B __ ## TN ## _formal_args)\
|
||||
{ TN ## _t *_p = N ## _start(B); if (!_p) return -1; TN ##_assign_to_pe(_p __ ## TN ## _call_args);\
|
||||
return 0; }\
|
||||
static inline int N ## _add(NS ## builder_t *B, const TN ## _t *p)\
|
||||
{ TN ## _t *_p = N ## _start(B); if (!_p) return -1; TN ##_copy_to_pe(_p, p); return 0; }\
|
||||
static inline int N ## _clone(NS ## builder_t *B, TN ## _struct_t p)\
|
||||
{ return 0 == flatcc_builder_table_add_copy(B, ID, p, S, A) ? -1 : 0; }\
|
||||
static inline int N ## _pick(NS ## builder_t *B, TT ## _table_t t)\
|
||||
{ TN ## _struct_t _p = N ## _get(t); return _p ? N ## _clone(B, _p) : 0; }
|
||||
|
||||
#define __flatbuffers_build_vector_field(ID, NS, N, TN, T, TT)\
|
||||
static inline int N ## _add(NS ## builder_t *B, TN ## _vec_ref_t ref)\
|
||||
{ TN ## _vec_ref_t *_p; return (ref && (_p = flatcc_builder_table_add_offset(B, ID))) ? ((*_p = ref), 0) : -1; }\
|
||||
static inline int N ## _start(NS ## builder_t *B)\
|
||||
{ return TN ## _vec_start(B); }\
|
||||
static inline int N ## _end_pe(NS ## builder_t *B)\
|
||||
{ return N ## _add(B, TN ## _vec_end_pe(B)); }\
|
||||
static inline int N ## _end(NS ## builder_t *B)\
|
||||
{ return N ## _add(B, TN ## _vec_end(B)); }\
|
||||
static inline int N ## _create_pe(NS ## builder_t *B, const T *data, size_t len)\
|
||||
{ return N ## _add(B, TN ## _vec_create_pe(B, data, len)); }\
|
||||
static inline int N ## _create(NS ## builder_t *B, const T *data, size_t len)\
|
||||
{ return N ## _add(B, TN ## _vec_create(B, data, len)); }\
|
||||
static inline int N ## _slice(NS ## builder_t *B, TN ## _vec_t vec, size_t index, size_t len)\
|
||||
{ return N ## _add(B, TN ## _vec_slice(B, vec, index, len)); }\
|
||||
static inline int N ## _clone(NS ## builder_t *B, TN ## _vec_t vec)\
|
||||
{ return N ## _add(B, TN ## _vec_clone(B, vec)); }\
|
||||
static inline int N ## _pick(NS ## builder_t *B, TT ## _table_t t)\
|
||||
{ TN ## _vec_t _p = N ## _get(t); return _p ? N ## _clone(B, _p) : 0; }\
|
||||
__flatbuffers_build_vector_ops(NS, N, N, TN, T)\
|
||||
|
||||
#define __flatbuffers_build_offset_vector_field(ID, NS, N, TN, TT)\
|
||||
static inline int N ## _add(NS ## builder_t *B, TN ## _vec_ref_t ref)\
|
||||
{ TN ## _vec_ref_t *_p; return (ref && (_p = flatcc_builder_table_add_offset(B, ID))) ? ((*_p = ref), 0) : -1; }\
|
||||
static inline int N ## _start(NS ## builder_t *B)\
|
||||
{ return flatcc_builder_start_offset_vector(B); }\
|
||||
static inline int N ## _end(NS ## builder_t *B)\
|
||||
{ return N ## _add(B, flatcc_builder_end_offset_vector(B)); }\
|
||||
static inline int N ## _create(NS ## builder_t *B, const TN ## _ref_t *data, size_t len)\
|
||||
{ return N ## _add(B, flatcc_builder_create_offset_vector(B, data, len)); }\
|
||||
__flatbuffers_build_offset_vector_ops(NS, N, N, TN)\
|
||||
static inline int N ## _clone(NS ## builder_t *B, TN ## _vec_t vec)\
|
||||
{ return N ## _add(B, TN ## _vec_clone(B, vec)); }\
|
||||
static inline int N ## _pick(NS ## builder_t *B, TT ## _table_t t)\
|
||||
{ TN ## _vec_t _p = N ## _get(t); return _p ? N ## _clone(B, _p) : 0; }
|
||||
|
||||
/* depends on N ## _add which differs for union member fields and ordinary fields */\
|
||||
#define __flatbuffers_build_string_field_ops(NS, N)\
|
||||
static inline int N ## _start(NS ## builder_t *B)\
|
||||
{ return flatcc_builder_start_string(B); }\
|
||||
static inline int N ## _end(NS ## builder_t *B)\
|
||||
{ return N ## _add(B, flatcc_builder_end_string(B)); }\
|
||||
static inline int N ## _create(NS ## builder_t *B, const char *s, size_t len)\
|
||||
{ return N ## _add(B, flatcc_builder_create_string(B, s, len)); }\
|
||||
static inline int N ## _create_str(NS ## builder_t *B, const char *s)\
|
||||
{ return N ## _add(B, flatcc_builder_create_string_str(B, s)); }\
|
||||
static inline int N ## _create_strn(NS ## builder_t *B, const char *s, size_t max_len)\
|
||||
{ return N ## _add(B, flatcc_builder_create_string_strn(B, s, max_len)); }\
|
||||
static inline int N ## _clone(NS ## builder_t *B, NS ## string_t string)\
|
||||
{ return N ## _add(B, NS ## string_clone(B, string)); }\
|
||||
static inline int N ## _slice(NS ## builder_t *B, NS ## string_t string, size_t index, size_t len)\
|
||||
{ return N ## _add(B, NS ## string_slice(B, string, index, len)); }\
|
||||
__flatbuffers_build_string_ops(NS, N)
|
||||
|
||||
#define __flatbuffers_build_string_field(ID, NS, N, TT)\
|
||||
static inline int N ## _add(NS ## builder_t *B, NS ## string_ref_t ref)\
|
||||
{ NS ## string_ref_t *_p; return (ref && (_p = flatcc_builder_table_add_offset(B, ID))) ? ((*_p = ref), 0) : -1; }\
|
||||
__flatbuffers_build_string_field_ops(NS, N)\
|
||||
static inline int N ## _pick(NS ## builder_t *B, TT ## _table_t t)\
|
||||
{ NS ## string_t _p = N ## _get(t); return _p ? N ## _clone(B, _p) : 0; }
|
||||
|
||||
#define __flatbuffers_build_table_vector_field(ID, NS, N, TN, TT)\
|
||||
__flatbuffers_build_offset_vector_field(ID, NS, N, TN, TT)\
|
||||
__flatbuffers_build_table_vector_ops(NS, N, TN)
|
||||
|
||||
#define __flatbuffers_build_union_vector_field(ID, NS, N, TN, TT)\
|
||||
static inline int N ## _add(NS ## builder_t *B, TN ## _union_vec_ref_t uvref)\
|
||||
{ NS ## vec_ref_t *_p; if (!uvref.type || !uvref.value) return uvref.type == uvref.value ? 0 : -1;\
|
||||
if (!(_p = flatcc_builder_table_add_offset(B, ID - 1))) return -1; *_p = uvref.type;\
|
||||
if (!(_p = flatcc_builder_table_add_offset(B, ID))) return -1; *_p = uvref.value; return 0; }\
|
||||
static inline int N ## _start(NS ## builder_t *B)\
|
||||
{ return flatcc_builder_start_union_vector(B); }\
|
||||
static inline int N ## _end(NS ## builder_t *B)\
|
||||
{ return N ## _add(B, flatcc_builder_end_union_vector(B)); }\
|
||||
static inline int N ## _create(NS ## builder_t *B, const TN ## _union_ref_t *data, size_t len)\
|
||||
{ return N ## _add(B, flatcc_builder_create_union_vector(B, data, len)); }\
|
||||
__flatbuffers_build_union_vector_ops(NS, N, N, TN)\
|
||||
static inline int N ## _clone(NS ## builder_t *B, TN ## _union_vec_t vec)\
|
||||
{ return N ## _add(B, TN ## _vec_clone(B, vec)); }\
|
||||
static inline int N ## _pick(NS ## builder_t *B, TT ## _table_t t)\
|
||||
{ TN ## _union_vec_t _p = N ## _union(t); return _p.type ? N ## _clone(B, _p) : 0; }
|
||||
|
||||
#define __flatbuffers_build_union_table_vector_value_field(NS, N, NU, M, T)\
|
||||
static inline int N ## _ ## M ## _push_start(NS ## builder_t *B)\
|
||||
{ return T ## _start(B); }\
|
||||
static inline NU ## _union_ref_t *N ## _ ## M ## _push_end(NS ## builder_t *B)\
|
||||
{ return NU ## _vec_push(B, NU ## _as_ ## M (T ## _end(B))); }\
|
||||
static inline NU ## _union_ref_t *N ## _ ## M ## _push(NS ## builder_t *B, T ## _ref_t ref)\
|
||||
{ return NU ## _vec_push(B, NU ## _as_ ## M (ref)); }\
|
||||
static inline NU ## _union_ref_t *N ## _ ## M ## _push_create(NS ## builder_t *B __ ## T ##_formal_args)\
|
||||
{ return NU ## _vec_push(B, NU ## _as_ ## M(T ## _create(B __ ## T ## _call_args))); }\
|
||||
static inline NU ## _union_ref_t *N ## _ ## M ## _push_clone(NS ## builder_t *B, T ## _table_t t)\
|
||||
{ return NU ## _vec_push(B, NU ## _as_ ## M(T ## _clone(B, t))); }
|
||||
|
||||
#define __flatbuffers_build_union_struct_vector_value_field(NS, N, NU, M, T)\
|
||||
static inline T ## _t *N ## _ ## M ## _push_start(NS ## builder_t *B)\
|
||||
{ return T ## _start(B); }\
|
||||
static inline NU ## _union_ref_t *N ## _ ## M ## _push_end(NS ## builder_t *B)\
|
||||
{ return NU ## _vec_push(B, NU ## _as_ ## M (T ## _end(B))); }\
|
||||
static inline NU ## _union_ref_t *N ## _ ## M ## _push(NS ## builder_t *B, T ## _ref_t ref)\
|
||||
{ return NU ## _vec_push(B, NU ## _as_ ## M (ref)); }\
|
||||
static inline NU ## _union_ref_t *N ## _ ## M ## _push_create(NS ## builder_t *B __ ## T ##_formal_args)\
|
||||
{ return NU ## _vec_push(B, NU ## _as_ ## M(T ## _create(B __ ## T ## _call_args))); }\
|
||||
static inline NU ## _union_ref_t *N ## _ ## M ## _push_clone(NS ## builder_t *B, T ## _struct_t p)\
|
||||
{ return NU ## _vec_push(B, NU ## _as_ ## M(T ## _clone(B, p))); }
|
||||
|
||||
#define __flatbuffers_build_union_string_vector_value_field(NS, N, NU, M)\
|
||||
static inline NU ## _union_ref_t *N ## _ ## M ## _push(NS ## builder_t *B, NS ## string_ref_t ref)\
|
||||
{ return NU ## _vec_push(B, NU ## _as_ ## M (ref)); }\
|
||||
static inline int N ## _ ## M ## _push_start(NS ## builder_t *B)\
|
||||
{ return NS ## string_start(B); }\
|
||||
static inline NU ## _union_ref_t *N ## _ ## M ## _push_end(NS ## builder_t *B)\
|
||||
{ return NU ## _vec_push(B, NU ## _as_ ## M(NS ## string_end(B))); }\
|
||||
static inline NU ## _union_ref_t *N ## _ ## M ## _push_create(NS ## builder_t *B, const char *s, size_t len)\
|
||||
{ return NU ## _vec_push(B, NU ## _as_ ## M(NS ## string_create(B, s, len))); }\
|
||||
static inline NU ## _union_ref_t *N ## _ ## M ## _push_create_str(NS ## builder_t *B, const char *s)\
|
||||
{ return NU ## _vec_push(B, NU ## _as_ ## M(NS ## string_create_str(B, s))); }\
|
||||
static inline NU ## _union_ref_t *N ## _ ## M ## _push_create_strn(NS ## builder_t *B, const char *s, size_t max_len)\
|
||||
{ return NU ## _vec_push(B, NU ## _as_ ## M(NS ## string_create_strn(B, s, max_len))); }\
|
||||
static inline NU ## _union_ref_t *N ## _ ## M ## _push_clone(NS ## builder_t *B, NS ## string_t string)\
|
||||
{ return NU ## _vec_push(B, NU ## _as_ ## M(NS ## string_clone(B, string))); }\
|
||||
static inline NU ## _union_ref_t *N ## _ ## M ## _push_slice(NS ## builder_t *B, NS ## string_t string, size_t index, size_t len)\
|
||||
{ return NU ## _vec_push(B, NU ## _as_ ## M(NS ## string_slice(B, string, index, len))); }
|
||||
|
||||
#define __flatbuffers_build_string_vector_field(ID, NS, N, TT)\
|
||||
__flatbuffers_build_offset_vector_field(ID, NS, N, NS ## string, TT)\
|
||||
__flatbuffers_build_string_vector_ops(NS, N)
|
||||
|
||||
#define __flatbuffers_char_formal_args , char v0
|
||||
#define __flatbuffers_char_call_args , v0
|
||||
#define __flatbuffers_uint8_formal_args , uint8_t v0
|
||||
#define __flatbuffers_uint8_call_args , v0
|
||||
#define __flatbuffers_int8_formal_args , int8_t v0
|
||||
#define __flatbuffers_int8_call_args , v0
|
||||
#define __flatbuffers_bool_formal_args , flatbuffers_bool_t v0
|
||||
#define __flatbuffers_bool_call_args , v0
|
||||
#define __flatbuffers_uint16_formal_args , uint16_t v0
|
||||
#define __flatbuffers_uint16_call_args , v0
|
||||
#define __flatbuffers_uint32_formal_args , uint32_t v0
|
||||
#define __flatbuffers_uint32_call_args , v0
|
||||
#define __flatbuffers_uint64_formal_args , uint64_t v0
|
||||
#define __flatbuffers_uint64_call_args , v0
|
||||
#define __flatbuffers_int16_formal_args , int16_t v0
|
||||
#define __flatbuffers_int16_call_args , v0
|
||||
#define __flatbuffers_int32_formal_args , int32_t v0
|
||||
#define __flatbuffers_int32_call_args , v0
|
||||
#define __flatbuffers_int64_formal_args , int64_t v0
|
||||
#define __flatbuffers_int64_call_args , v0
|
||||
#define __flatbuffers_float_formal_args , float v0
|
||||
#define __flatbuffers_float_call_args , v0
|
||||
#define __flatbuffers_double_formal_args , double v0
|
||||
#define __flatbuffers_double_call_args , v0
|
||||
|
||||
__flatbuffers_build_scalar(flatbuffers_, flatbuffers_char, char)
|
||||
__flatbuffers_build_scalar(flatbuffers_, flatbuffers_uint8, uint8_t)
|
||||
__flatbuffers_build_scalar(flatbuffers_, flatbuffers_int8, int8_t)
|
||||
__flatbuffers_build_scalar(flatbuffers_, flatbuffers_bool, flatbuffers_bool_t)
|
||||
__flatbuffers_build_scalar(flatbuffers_, flatbuffers_uint16, uint16_t)
|
||||
__flatbuffers_build_scalar(flatbuffers_, flatbuffers_uint32, uint32_t)
|
||||
__flatbuffers_build_scalar(flatbuffers_, flatbuffers_uint64, uint64_t)
|
||||
__flatbuffers_build_scalar(flatbuffers_, flatbuffers_int16, int16_t)
|
||||
__flatbuffers_build_scalar(flatbuffers_, flatbuffers_int32, int32_t)
|
||||
__flatbuffers_build_scalar(flatbuffers_, flatbuffers_int64, int64_t)
|
||||
__flatbuffers_build_scalar(flatbuffers_, flatbuffers_float, float)
|
||||
__flatbuffers_build_scalar(flatbuffers_, flatbuffers_double, double)
|
||||
|
||||
__flatbuffers_build_string(flatbuffers_)
|
||||
|
||||
__flatbuffers_build_buffer(flatbuffers_)
|
||||
#include "flatcc/flatcc_epilogue.h"
|
||||
#endif /* FLATBUFFERS_COMMON_BUILDER_H */
|
||||
578
nostrdb/src/bindings/c/flatbuffers_common_reader.h
Normal file
578
nostrdb/src/bindings/c/flatbuffers_common_reader.h
Normal file
@@ -0,0 +1,578 @@
|
||||
#ifndef FLATBUFFERS_COMMON_READER_H
|
||||
#define FLATBUFFERS_COMMON_READER_H
|
||||
|
||||
/* Generated by flatcc 0.6.1 FlatBuffers schema compiler for C by dvide.com */
|
||||
|
||||
/* Common FlatBuffers read functionality for C. */
|
||||
|
||||
#include "flatcc/flatcc_prologue.h"
|
||||
#include "flatcc/flatcc_flatbuffers.h"
|
||||
|
||||
|
||||
#define __flatbuffers_read_scalar_at_byteoffset(N, p, o) N ## _read_from_pe((uint8_t *)(p) + (o))
|
||||
#define __flatbuffers_read_scalar(N, p) N ## _read_from_pe(p)
|
||||
#define __flatbuffers_read_vt(ID, offset, t)\
|
||||
flatbuffers_voffset_t offset = 0;\
|
||||
{ flatbuffers_voffset_t id__tmp, *vt__tmp;\
|
||||
FLATCC_ASSERT(t != 0 && "null pointer table access");\
|
||||
id__tmp = ID;\
|
||||
vt__tmp = (flatbuffers_voffset_t *)((uint8_t *)(t) -\
|
||||
__flatbuffers_soffset_read_from_pe(t));\
|
||||
if (__flatbuffers_voffset_read_from_pe(vt__tmp) >= sizeof(vt__tmp[0]) * (id__tmp + 3u)) {\
|
||||
offset = __flatbuffers_voffset_read_from_pe(vt__tmp + id__tmp + 2);\
|
||||
}\
|
||||
}
|
||||
#define __flatbuffers_field_present(ID, t) { __flatbuffers_read_vt(ID, offset__tmp, t) return offset__tmp != 0; }
|
||||
#define __flatbuffers_scalar_field(T, ID, t)\
|
||||
{\
|
||||
__flatbuffers_read_vt(ID, offset__tmp, t)\
|
||||
if (offset__tmp) {\
|
||||
return (const T *)((uint8_t *)(t) + offset__tmp);\
|
||||
}\
|
||||
return 0;\
|
||||
}
|
||||
#define __flatbuffers_define_scalar_field(ID, N, NK, TK, T, V)\
|
||||
static inline T N ## _ ## NK ## _get(N ## _table_t t__tmp)\
|
||||
{ __flatbuffers_read_vt(ID, offset__tmp, t__tmp)\
|
||||
return offset__tmp ? __flatbuffers_read_scalar_at_byteoffset(TK, t__tmp, offset__tmp) : V;\
|
||||
}\
|
||||
static inline T N ## _ ## NK(N ## _table_t t__tmp)\
|
||||
{ __flatbuffers_read_vt(ID, offset__tmp, t__tmp)\
|
||||
return offset__tmp ? __flatbuffers_read_scalar_at_byteoffset(TK, t__tmp, offset__tmp) : V;\
|
||||
}\
|
||||
static inline const T *N ## _ ## NK ## _get_ptr(N ## _table_t t__tmp)\
|
||||
__flatbuffers_scalar_field(T, ID, t__tmp)\
|
||||
static inline int N ## _ ## NK ## _is_present(N ## _table_t t__tmp)\
|
||||
__flatbuffers_field_present(ID, t__tmp)\
|
||||
__flatbuffers_define_scan_by_scalar_field(N, NK, T)
|
||||
#define __flatbuffers_define_scalar_optional_field(ID, N, NK, TK, T, V)\
|
||||
__flatbuffers_define_scalar_field(ID, N, NK, TK, T, V)\
|
||||
static inline TK ## _option_t N ## _ ## NK ## _option(N ## _table_t t__tmp)\
|
||||
{ TK ## _option_t ret; __flatbuffers_read_vt(ID, offset__tmp, t__tmp)\
|
||||
ret.is_null = offset__tmp == 0; ret.value = offset__tmp ?\
|
||||
__flatbuffers_read_scalar_at_byteoffset(TK, t__tmp, offset__tmp) : V;\
|
||||
return ret; }
|
||||
#define __flatbuffers_struct_field(T, ID, t, r)\
|
||||
{\
|
||||
__flatbuffers_read_vt(ID, offset__tmp, t)\
|
||||
if (offset__tmp) {\
|
||||
return (T)((uint8_t *)(t) + offset__tmp);\
|
||||
}\
|
||||
FLATCC_ASSERT(!(r) && "required field missing");\
|
||||
return 0;\
|
||||
}
|
||||
#define __flatbuffers_offset_field(T, ID, t, r, adjust)\
|
||||
{\
|
||||
flatbuffers_uoffset_t *elem__tmp;\
|
||||
__flatbuffers_read_vt(ID, offset__tmp, t)\
|
||||
if (offset__tmp) {\
|
||||
elem__tmp = (flatbuffers_uoffset_t *)((uint8_t *)(t) + offset__tmp);\
|
||||
/* Add sizeof so C api can have raw access past header field. */\
|
||||
return (T)((uint8_t *)(elem__tmp) + adjust +\
|
||||
__flatbuffers_uoffset_read_from_pe(elem__tmp));\
|
||||
}\
|
||||
FLATCC_ASSERT(!(r) && "required field missing");\
|
||||
return 0;\
|
||||
}
|
||||
#define __flatbuffers_vector_field(T, ID, t, r) __flatbuffers_offset_field(T, ID, t, r, sizeof(flatbuffers_uoffset_t))
|
||||
#define __flatbuffers_table_field(T, ID, t, r) __flatbuffers_offset_field(T, ID, t, r, 0)
|
||||
#define __flatbuffers_define_struct_field(ID, N, NK, T, r)\
|
||||
static inline T N ## _ ## NK ## _get(N ## _table_t t__tmp)\
|
||||
__flatbuffers_struct_field(T, ID, t__tmp, r)\
|
||||
static inline T N ## _ ## NK(N ## _table_t t__tmp)\
|
||||
__flatbuffers_struct_field(T, ID, t__tmp, r)\
|
||||
static inline int N ## _ ## NK ## _is_present(N ## _table_t t__tmp)\
|
||||
__flatbuffers_field_present(ID, t__tmp)
|
||||
#define __flatbuffers_define_vector_field(ID, N, NK, T, r)\
|
||||
static inline T N ## _ ## NK ## _get(N ## _table_t t__tmp)\
|
||||
__flatbuffers_vector_field(T, ID, t__tmp, r)\
|
||||
static inline T N ## _ ## NK(N ## _table_t t__tmp)\
|
||||
__flatbuffers_vector_field(T, ID, t__tmp, r)\
|
||||
static inline int N ## _ ## NK ## _is_present(N ## _table_t t__tmp)\
|
||||
__flatbuffers_field_present(ID, t__tmp)
|
||||
#define __flatbuffers_define_table_field(ID, N, NK, T, r)\
|
||||
static inline T N ## _ ## NK ## _get(N ## _table_t t__tmp)\
|
||||
__flatbuffers_table_field(T, ID, t__tmp, r)\
|
||||
static inline T N ## _ ## NK(N ## _table_t t__tmp)\
|
||||
__flatbuffers_table_field(T, ID, t__tmp, r)\
|
||||
static inline int N ## _ ## NK ## _is_present(N ## _table_t t__tmp)\
|
||||
__flatbuffers_field_present(ID, t__tmp)
|
||||
#define __flatbuffers_define_string_field(ID, N, NK, r)\
|
||||
static inline flatbuffers_string_t N ## _ ## NK ## _get(N ## _table_t t__tmp)\
|
||||
__flatbuffers_vector_field(flatbuffers_string_t, ID, t__tmp, r)\
|
||||
static inline flatbuffers_string_t N ## _ ## NK(N ## _table_t t__tmp)\
|
||||
__flatbuffers_vector_field(flatbuffers_string_t, ID, t__tmp, r)\
|
||||
static inline int N ## _ ## NK ## _is_present(N ## _table_t t__tmp)\
|
||||
__flatbuffers_field_present(ID, t__tmp)\
|
||||
__flatbuffers_define_scan_by_string_field(N, NK)
|
||||
#define __flatbuffers_vec_len(vec)\
|
||||
{ return (vec) ? (size_t)__flatbuffers_uoffset_read_from_pe((flatbuffers_uoffset_t *)vec - 1) : 0; }
|
||||
#define __flatbuffers_string_len(s) __flatbuffers_vec_len(s)
|
||||
static inline size_t flatbuffers_vec_len(const void *vec)
|
||||
__flatbuffers_vec_len(vec)
|
||||
#define __flatbuffers_scalar_vec_at(N, vec, i)\
|
||||
{ FLATCC_ASSERT(flatbuffers_vec_len(vec) > (i) && "index out of range");\
|
||||
return __flatbuffers_read_scalar(N, &(vec)[i]); }
|
||||
#define __flatbuffers_struct_vec_at(vec, i)\
|
||||
{ FLATCC_ASSERT(flatbuffers_vec_len(vec) > (i) && "index out of range"); return (vec) + (i); }
|
||||
/* `adjust` skips past the header for string vectors. */
|
||||
#define __flatbuffers_offset_vec_at(T, vec, i, adjust)\
|
||||
{ const flatbuffers_uoffset_t *elem__tmp = (vec) + (i);\
|
||||
FLATCC_ASSERT(flatbuffers_vec_len(vec) > (i) && "index out of range");\
|
||||
return (T)((uint8_t *)(elem__tmp) + (size_t)__flatbuffers_uoffset_read_from_pe(elem__tmp) + (adjust)); }
|
||||
#define __flatbuffers_define_scalar_vec_len(N)\
|
||||
static inline size_t N ## _vec_len(N ##_vec_t vec__tmp)\
|
||||
{ return flatbuffers_vec_len(vec__tmp); }
|
||||
#define __flatbuffers_define_scalar_vec_at(N, T) \
|
||||
static inline T N ## _vec_at(N ## _vec_t vec__tmp, size_t i__tmp)\
|
||||
__flatbuffers_scalar_vec_at(N, vec__tmp, i__tmp)
|
||||
typedef const char *flatbuffers_string_t;
|
||||
static inline size_t flatbuffers_string_len(flatbuffers_string_t s)
|
||||
__flatbuffers_string_len(s)
|
||||
typedef const flatbuffers_uoffset_t *flatbuffers_string_vec_t;
|
||||
typedef flatbuffers_uoffset_t *flatbuffers_string_mutable_vec_t;
|
||||
static inline size_t flatbuffers_string_vec_len(flatbuffers_string_vec_t vec)
|
||||
__flatbuffers_vec_len(vec)
|
||||
static inline flatbuffers_string_t flatbuffers_string_vec_at(flatbuffers_string_vec_t vec, size_t i)
|
||||
__flatbuffers_offset_vec_at(flatbuffers_string_t, vec, i, sizeof(vec[0]))
|
||||
typedef const void *flatbuffers_generic_t;
|
||||
typedef void *flatbuffers_mutable_generic_t;
|
||||
static inline flatbuffers_string_t flatbuffers_string_cast_from_generic(const flatbuffers_generic_t p)
|
||||
{ return p ? ((const char *)p) + __flatbuffers_uoffset__size() : 0; }
|
||||
typedef const flatbuffers_uoffset_t *flatbuffers_generic_vec_t;
|
||||
typedef flatbuffers_uoffset_t *flatbuffers_generic_table_mutable_vec_t;
|
||||
static inline size_t flatbuffers_generic_vec_len(flatbuffers_generic_vec_t vec)
|
||||
__flatbuffers_vec_len(vec)
|
||||
static inline flatbuffers_generic_t flatbuffers_generic_vec_at(flatbuffers_generic_vec_t vec, size_t i)
|
||||
__flatbuffers_offset_vec_at(flatbuffers_generic_t, vec, i, 0)
|
||||
static inline flatbuffers_generic_t flatbuffers_generic_vec_at_as_string(flatbuffers_generic_vec_t vec, size_t i)
|
||||
__flatbuffers_offset_vec_at(flatbuffers_generic_t, vec, i, sizeof(vec[0]))
|
||||
typedef struct flatbuffers_union {
|
||||
flatbuffers_union_type_t type;
|
||||
flatbuffers_generic_t value;
|
||||
} flatbuffers_union_t;
|
||||
typedef struct flatbuffers_union_vec {
|
||||
const flatbuffers_union_type_t *type;
|
||||
const flatbuffers_uoffset_t *value;
|
||||
} flatbuffers_union_vec_t;
|
||||
typedef struct flatbuffers_mutable_union {
|
||||
flatbuffers_union_type_t type;
|
||||
flatbuffers_mutable_generic_t value;
|
||||
} flatbuffers_mutable_union_t;
|
||||
typedef struct flatbuffers_mutable_union_vec {
|
||||
flatbuffers_union_type_t *type;
|
||||
flatbuffers_uoffset_t *value;
|
||||
} flatbuffers_mutable_union_vec_t;
|
||||
static inline flatbuffers_mutable_union_t flatbuffers_mutable_union_cast(flatbuffers_union_t u__tmp)\
|
||||
{ flatbuffers_mutable_union_t mu = { u__tmp.type, (flatbuffers_mutable_generic_t)u__tmp.value };\
|
||||
return mu; }
|
||||
static inline flatbuffers_mutable_union_vec_t flatbuffers_mutable_union_vec_cast(flatbuffers_union_vec_t uv__tmp)\
|
||||
{ flatbuffers_mutable_union_vec_t muv =\
|
||||
{ (flatbuffers_union_type_t *)uv__tmp.type, (flatbuffers_uoffset_t *)uv__tmp.value }; return muv; }
|
||||
#define __flatbuffers_union_type_field(ID, t)\
|
||||
{\
|
||||
__flatbuffers_read_vt(ID, offset__tmp, t)\
|
||||
return offset__tmp ? __flatbuffers_read_scalar_at_byteoffset(__flatbuffers_utype, t, offset__tmp) : 0;\
|
||||
}
|
||||
static inline flatbuffers_string_t flatbuffers_string_cast_from_union(const flatbuffers_union_t u__tmp)\
|
||||
{ return flatbuffers_string_cast_from_generic(u__tmp.value); }
|
||||
#define __flatbuffers_define_union_field(NS, ID, N, NK, T, r)\
|
||||
static inline T ## _union_type_t N ## _ ## NK ## _type_get(N ## _table_t t__tmp)\
|
||||
__## NS ## union_type_field(((ID) - 1), t__tmp)\
|
||||
static inline NS ## generic_t N ## _ ## NK ## _get(N ## _table_t t__tmp)\
|
||||
__## NS ## table_field(NS ## generic_t, ID, t__tmp, r)\
|
||||
static inline T ## _union_type_t N ## _ ## NK ## _type(N ## _table_t t__tmp)\
|
||||
__## NS ## union_type_field(((ID) - 1), t__tmp)\
|
||||
static inline NS ## generic_t N ## _ ## NK(N ## _table_t t__tmp)\
|
||||
__## NS ## table_field(NS ## generic_t, ID, t__tmp, r)\
|
||||
static inline int N ## _ ## NK ## _is_present(N ## _table_t t__tmp)\
|
||||
__## NS ## field_present(ID, t__tmp)\
|
||||
static inline T ## _union_t N ## _ ## NK ## _union(N ## _table_t t__tmp)\
|
||||
{ T ## _union_t u__tmp = { 0, 0 }; u__tmp.type = N ## _ ## NK ## _type_get(t__tmp);\
|
||||
if (u__tmp.type == 0) return u__tmp; u__tmp.value = N ## _ ## NK ## _get(t__tmp); return u__tmp; }\
|
||||
static inline NS ## string_t N ## _ ## NK ## _as_string(N ## _table_t t__tmp)\
|
||||
{ return NS ## string_cast_from_generic(N ## _ ## NK ## _get(t__tmp)); }\
|
||||
|
||||
#define __flatbuffers_define_union_vector_ops(NS, T)\
|
||||
static inline size_t T ## _union_vec_len(T ## _union_vec_t uv__tmp)\
|
||||
{ return NS ## vec_len(uv__tmp.type); }\
|
||||
static inline T ## _union_t T ## _union_vec_at(T ## _union_vec_t uv__tmp, size_t i__tmp)\
|
||||
{ T ## _union_t u__tmp = { 0, 0 }; size_t n__tmp = NS ## vec_len(uv__tmp.type);\
|
||||
FLATCC_ASSERT(n__tmp > (i__tmp) && "index out of range"); u__tmp.type = uv__tmp.type[i__tmp];\
|
||||
/* Unknown type is treated as NONE for schema evolution. */\
|
||||
if (u__tmp.type == 0) return u__tmp;\
|
||||
u__tmp.value = NS ## generic_vec_at(uv__tmp.value, i__tmp); return u__tmp; }\
|
||||
static inline NS ## string_t T ## _union_vec_at_as_string(T ## _union_vec_t uv__tmp, size_t i__tmp)\
|
||||
{ return (NS ## string_t) NS ## generic_vec_at_as_string(uv__tmp.value, i__tmp); }\
|
||||
|
||||
#define __flatbuffers_define_union_vector(NS, T)\
|
||||
typedef NS ## union_vec_t T ## _union_vec_t;\
|
||||
typedef NS ## mutable_union_vec_t T ## _mutable_union_vec_t;\
|
||||
static inline T ## _mutable_union_vec_t T ## _mutable_union_vec_cast(T ## _union_vec_t u__tmp)\
|
||||
{ return NS ## mutable_union_vec_cast(u__tmp); }\
|
||||
__## NS ## define_union_vector_ops(NS, T)
|
||||
#define __flatbuffers_define_union(NS, T)\
|
||||
typedef NS ## union_t T ## _union_t;\
|
||||
typedef NS ## mutable_union_t T ## _mutable_union_t;\
|
||||
static inline T ## _mutable_union_t T ## _mutable_union_cast(T ## _union_t u__tmp)\
|
||||
{ return NS ## mutable_union_cast(u__tmp); }\
|
||||
__## NS ## define_union_vector(NS, T)
|
||||
#define __flatbuffers_define_union_vector_field(NS, ID, N, NK, T, r)\
|
||||
__## NS ## define_vector_field(ID - 1, N, NK ## _type, T ## _vec_t, r)\
|
||||
__## NS ## define_vector_field(ID, N, NK, flatbuffers_generic_vec_t, r)\
|
||||
static inline T ## _union_vec_t N ## _ ## NK ## _union(N ## _table_t t__tmp)\
|
||||
{ T ## _union_vec_t uv__tmp; uv__tmp.type = N ## _ ## NK ## _type_get(t__tmp);\
|
||||
uv__tmp.value = N ## _ ## NK(t__tmp);\
|
||||
FLATCC_ASSERT(NS ## vec_len(uv__tmp.type) == NS ## vec_len(uv__tmp.value)\
|
||||
&& "union vector type length mismatch"); return uv__tmp; }
|
||||
#include <string.h>
|
||||
static const size_t flatbuffers_not_found = (size_t)-1;
|
||||
static const size_t flatbuffers_end = (size_t)-1;
|
||||
#define __flatbuffers_identity(n) (n)
|
||||
#define __flatbuffers_min(a, b) ((a) < (b) ? (a) : (b))
|
||||
/* Subtraction doesn't work for unsigned types. */
|
||||
#define __flatbuffers_scalar_cmp(x, y, n) ((x) < (y) ? -1 : (x) > (y))
|
||||
static inline int __flatbuffers_string_n_cmp(flatbuffers_string_t v, const char *s, size_t n)
|
||||
{ size_t nv = flatbuffers_string_len(v); int x = strncmp(v, s, nv < n ? nv : n);
|
||||
return x != 0 ? x : nv < n ? -1 : nv > n; }
|
||||
/* `n` arg unused, but needed by string find macro expansion. */
|
||||
static inline int __flatbuffers_string_cmp(flatbuffers_string_t v, const char *s, size_t n) { (void)n; return strcmp(v, s); }
|
||||
/* A = identity if searching scalar vectors rather than key fields. */
|
||||
/* Returns lowest matching index or not_found. */
|
||||
#define __flatbuffers_find_by_field(A, V, E, L, K, Kn, T, D)\
|
||||
{ T v__tmp; size_t a__tmp = 0, b__tmp, m__tmp; if (!(b__tmp = L(V))) { return flatbuffers_not_found; }\
|
||||
--b__tmp;\
|
||||
while (a__tmp < b__tmp) {\
|
||||
m__tmp = a__tmp + ((b__tmp - a__tmp) >> 1);\
|
||||
v__tmp = A(E(V, m__tmp));\
|
||||
if ((D(v__tmp, (K), (Kn))) < 0) {\
|
||||
a__tmp = m__tmp + 1;\
|
||||
} else {\
|
||||
b__tmp = m__tmp;\
|
||||
}\
|
||||
}\
|
||||
if (a__tmp == b__tmp) {\
|
||||
v__tmp = A(E(V, a__tmp));\
|
||||
if (D(v__tmp, (K), (Kn)) == 0) {\
|
||||
return a__tmp;\
|
||||
}\
|
||||
}\
|
||||
return flatbuffers_not_found;\
|
||||
}
|
||||
#define __flatbuffers_find_by_scalar_field(A, V, E, L, K, T)\
|
||||
__flatbuffers_find_by_field(A, V, E, L, K, 0, T, __flatbuffers_scalar_cmp)
|
||||
#define __flatbuffers_find_by_string_field(A, V, E, L, K)\
|
||||
__flatbuffers_find_by_field(A, V, E, L, K, 0, flatbuffers_string_t, __flatbuffers_string_cmp)
|
||||
#define __flatbuffers_find_by_string_n_field(A, V, E, L, K, Kn)\
|
||||
__flatbuffers_find_by_field(A, V, E, L, K, Kn, flatbuffers_string_t, __flatbuffers_string_n_cmp)
|
||||
#define __flatbuffers_define_find_by_scalar_field(N, NK, TK)\
|
||||
static inline size_t N ## _vec_find_by_ ## NK(N ## _vec_t vec__tmp, TK key__tmp)\
|
||||
__flatbuffers_find_by_scalar_field(N ## _ ## NK, vec__tmp, N ## _vec_at, N ## _vec_len, key__tmp, TK)
|
||||
#define __flatbuffers_define_scalar_find(N, T)\
|
||||
static inline size_t N ## _vec_find(N ## _vec_t vec__tmp, T key__tmp)\
|
||||
__flatbuffers_find_by_scalar_field(__flatbuffers_identity, vec__tmp, N ## _vec_at, N ## _vec_len, key__tmp, T)
|
||||
#define __flatbuffers_define_find_by_string_field(N, NK) \
|
||||
/* Note: find only works on vectors sorted by this field. */\
|
||||
static inline size_t N ## _vec_find_by_ ## NK(N ## _vec_t vec__tmp, const char *s__tmp)\
|
||||
__flatbuffers_find_by_string_field(N ## _ ## NK, vec__tmp, N ## _vec_at, N ## _vec_len, s__tmp)\
|
||||
static inline size_t N ## _vec_find_n_by_ ## NK(N ## _vec_t vec__tmp, const char *s__tmp, size_t n__tmp)\
|
||||
__flatbuffers_find_by_string_n_field(N ## _ ## NK, vec__tmp, N ## _vec_at, N ## _vec_len, s__tmp, n__tmp)
|
||||
#define __flatbuffers_define_default_find_by_scalar_field(N, NK, TK)\
|
||||
static inline size_t N ## _vec_find(N ## _vec_t vec__tmp, TK key__tmp)\
|
||||
{ return N ## _vec_find_by_ ## NK(vec__tmp, key__tmp); }
|
||||
#define __flatbuffers_define_default_find_by_string_field(N, NK) \
|
||||
static inline size_t N ## _vec_find(N ## _vec_t vec__tmp, const char *s__tmp)\
|
||||
{ return N ## _vec_find_by_ ## NK(vec__tmp, s__tmp); }\
|
||||
static inline size_t N ## _vec_find_n(N ## _vec_t vec__tmp, const char *s__tmp, size_t n__tmp)\
|
||||
{ return N ## _vec_find_n_by_ ## NK(vec__tmp, s__tmp, n__tmp); }
|
||||
/* A = identity if searching scalar vectors rather than key fields. */
|
||||
/* Returns lowest matching index or not_found. */
|
||||
#define __flatbuffers_scan_by_field(b, e, A, V, E, L, K, Kn, T, D)\
|
||||
{ T v__tmp; size_t i__tmp;\
|
||||
for (i__tmp = b; i__tmp < e; ++i__tmp) {\
|
||||
v__tmp = A(E(V, i__tmp));\
|
||||
if (D(v__tmp, (K), (Kn)) == 0) {\
|
||||
return i__tmp;\
|
||||
}\
|
||||
}\
|
||||
return flatbuffers_not_found;\
|
||||
}
|
||||
#define __flatbuffers_rscan_by_field(b, e, A, V, E, L, K, Kn, T, D)\
|
||||
{ T v__tmp; size_t i__tmp = e;\
|
||||
while (i__tmp-- > b) {\
|
||||
v__tmp = A(E(V, i__tmp));\
|
||||
if (D(v__tmp, (K), (Kn)) == 0) {\
|
||||
return i__tmp;\
|
||||
}\
|
||||
}\
|
||||
return flatbuffers_not_found;\
|
||||
}
|
||||
#define __flatbuffers_scan_by_scalar_field(b, e, A, V, E, L, K, T)\
|
||||
__flatbuffers_scan_by_field(b, e, A, V, E, L, K, 0, T, __flatbuffers_scalar_cmp)
|
||||
#define __flatbuffers_scan_by_string_field(b, e, A, V, E, L, K)\
|
||||
__flatbuffers_scan_by_field(b, e, A, V, E, L, K, 0, flatbuffers_string_t, __flatbuffers_string_cmp)
|
||||
#define __flatbuffers_scan_by_string_n_field(b, e, A, V, E, L, K, Kn)\
|
||||
__flatbuffers_scan_by_field(b, e, A, V, E, L, K, Kn, flatbuffers_string_t, __flatbuffers_string_n_cmp)
|
||||
#define __flatbuffers_rscan_by_scalar_field(b, e, A, V, E, L, K, T)\
|
||||
__flatbuffers_rscan_by_field(b, e, A, V, E, L, K, 0, T, __flatbuffers_scalar_cmp)
|
||||
#define __flatbuffers_rscan_by_string_field(b, e, A, V, E, L, K)\
|
||||
__flatbuffers_rscan_by_field(b, e, A, V, E, L, K, 0, flatbuffers_string_t, __flatbuffers_string_cmp)
|
||||
#define __flatbuffers_rscan_by_string_n_field(b, e, A, V, E, L, K, Kn)\
|
||||
__flatbuffers_rscan_by_field(b, e, A, V, E, L, K, Kn, flatbuffers_string_t, __flatbuffers_string_n_cmp)
|
||||
#define __flatbuffers_define_scan_by_scalar_field(N, NK, T)\
|
||||
static inline size_t N ## _vec_scan_by_ ## NK(N ## _vec_t vec__tmp, T key__tmp)\
|
||||
__flatbuffers_scan_by_scalar_field(0, N ## _vec_len(vec__tmp), N ## _ ## NK ## _get, vec__tmp, N ## _vec_at, N ## _vec_len, key__tmp, T)\
|
||||
static inline size_t N ## _vec_scan_ex_by_ ## NK(N ## _vec_t vec__tmp, size_t begin__tmp, size_t end__tmp, T key__tmp)\
|
||||
__flatbuffers_scan_by_scalar_field(begin__tmp, __flatbuffers_min(end__tmp, N ## _vec_len(vec__tmp)), N ## _ ## NK ## _get, vec__tmp, N ## _vec_at, N ## _vec_len, key__tmp, T)\
|
||||
static inline size_t N ## _vec_rscan_by_ ## NK(N ## _vec_t vec__tmp, T key__tmp)\
|
||||
__flatbuffers_rscan_by_scalar_field(0, N ## _vec_len(vec__tmp), N ## _ ## NK ## _get, vec__tmp, N ## _vec_at, N ## _vec_len, key__tmp, T)\
|
||||
static inline size_t N ## _vec_rscan_ex_by_ ## NK(N ## _vec_t vec__tmp, size_t begin__tmp, size_t end__tmp, T key__tmp)\
|
||||
__flatbuffers_rscan_by_scalar_field(begin__tmp, __flatbuffers_min(end__tmp, N ## _vec_len(vec__tmp)), N ## _ ## NK ## _get, vec__tmp, N ## _vec_at, N ## _vec_len, key__tmp, T)
|
||||
#define __flatbuffers_define_scalar_scan(N, T)\
|
||||
static inline size_t N ## _vec_scan(N ## _vec_t vec__tmp, T key__tmp)\
|
||||
__flatbuffers_scan_by_scalar_field(0, N ## _vec_len(vec__tmp), __flatbuffers_identity, vec__tmp, N ## _vec_at, N ## _vec_len, key__tmp, T)\
|
||||
static inline size_t N ## _vec_scan_ex(N ## _vec_t vec__tmp, size_t begin__tmp, size_t end__tmp, T key__tmp)\
|
||||
__flatbuffers_scan_by_scalar_field(begin__tmp, __flatbuffers_min(end__tmp, N ## _vec_len(vec__tmp)), __flatbuffers_identity, vec__tmp, N ## _vec_at, N ## _vec_len, key__tmp, T)\
|
||||
static inline size_t N ## _vec_rscan(N ## _vec_t vec__tmp, T key__tmp)\
|
||||
__flatbuffers_rscan_by_scalar_field(0, N ## _vec_len(vec__tmp), __flatbuffers_identity, vec__tmp, N ## _vec_at, N ## _vec_len, key__tmp, T)\
|
||||
static inline size_t N ## _vec_rscan_ex(N ## _vec_t vec__tmp, size_t begin__tmp, size_t end__tmp, T key__tmp)\
|
||||
__flatbuffers_rscan_by_scalar_field(begin__tmp, __flatbuffers_min(end__tmp, N ## _vec_len(vec__tmp)), __flatbuffers_identity, vec__tmp, N ## _vec_at, N ## _vec_len, key__tmp, T)
|
||||
#define __flatbuffers_define_scan_by_string_field(N, NK) \
|
||||
static inline size_t N ## _vec_scan_by_ ## NK(N ## _vec_t vec__tmp, const char *s__tmp)\
|
||||
__flatbuffers_scan_by_string_field(0, N ## _vec_len(vec__tmp), N ## _ ## NK ## _get, vec__tmp, N ## _vec_at, N ## _vec_len, s__tmp)\
|
||||
static inline size_t N ## _vec_scan_n_by_ ## NK(N ## _vec_t vec__tmp, const char *s__tmp, size_t n__tmp)\
|
||||
__flatbuffers_scan_by_string_n_field(0, N ## _vec_len(vec__tmp), N ## _ ## NK ## _get, vec__tmp, N ## _vec_at, N ## _vec_len, s__tmp, n__tmp)\
|
||||
static inline size_t N ## _vec_scan_ex_by_ ## NK(N ## _vec_t vec__tmp, size_t begin__tmp, size_t end__tmp, const char *s__tmp)\
|
||||
__flatbuffers_scan_by_string_field(begin__tmp, __flatbuffers_min(end__tmp, N ## _vec_len(vec__tmp)), N ## _ ## NK ## _get, vec__tmp, N ## _vec_at, N ## _vec_len, s__tmp)\
|
||||
static inline size_t N ## _vec_scan_ex_n_by_ ## NK(N ## _vec_t vec__tmp, size_t begin__tmp, size_t end__tmp, const char *s__tmp, size_t n__tmp)\
|
||||
__flatbuffers_scan_by_string_n_field(begin__tmp, __flatbuffers_min( end__tmp, N ## _vec_len(vec__tmp)), N ## _ ## NK ## _get, vec__tmp, N ## _vec_at, N ## _vec_len, s__tmp, n__tmp)\
|
||||
static inline size_t N ## _vec_rscan_by_ ## NK(N ## _vec_t vec__tmp, const char *s__tmp)\
|
||||
__flatbuffers_rscan_by_string_field(0, N ## _vec_len(vec__tmp), N ## _ ## NK ## _get, vec__tmp, N ## _vec_at, N ## _vec_len, s__tmp)\
|
||||
static inline size_t N ## _vec_rscan_n_by_ ## NK(N ## _vec_t vec__tmp, const char *s__tmp, size_t n__tmp)\
|
||||
__flatbuffers_rscan_by_string_n_field(0, N ## _vec_len(vec__tmp), N ## _ ## NK ## _get, vec__tmp, N ## _vec_at, N ## _vec_len, s__tmp, n__tmp)\
|
||||
static inline size_t N ## _vec_rscan_ex_by_ ## NK(N ## _vec_t vec__tmp, size_t begin__tmp, size_t end__tmp, const char *s__tmp)\
|
||||
__flatbuffers_rscan_by_string_field(begin__tmp, __flatbuffers_min(end__tmp, N ## _vec_len(vec__tmp)), N ## _ ## NK ## _get, vec__tmp, N ## _vec_at, N ## _vec_len, s__tmp)\
|
||||
static inline size_t N ## _vec_rscan_ex_n_by_ ## NK(N ## _vec_t vec__tmp, size_t begin__tmp, size_t end__tmp, const char *s__tmp, size_t n__tmp)\
|
||||
__flatbuffers_rscan_by_string_n_field(begin__tmp, __flatbuffers_min( end__tmp, N ## _vec_len(vec__tmp)), N ## _ ## NK ## _get, vec__tmp, N ## _vec_at, N ## _vec_len, s__tmp, n__tmp)
|
||||
#define __flatbuffers_define_default_scan_by_scalar_field(N, NK, TK)\
|
||||
static inline size_t N ## _vec_scan(N ## _vec_t vec__tmp, TK key__tmp)\
|
||||
{ return N ## _vec_scan_by_ ## NK(vec__tmp, key__tmp); }\
|
||||
static inline size_t N ## _vec_scan_ex(N ## _vec_t vec__tmp, size_t begin__tmp, size_t end__tmp, TK key__tmp)\
|
||||
{ return N ## _vec_scan_ex_by_ ## NK(vec__tmp, begin__tmp, end__tmp, key__tmp); }\
|
||||
static inline size_t N ## _vec_rscan(N ## _vec_t vec__tmp, TK key__tmp)\
|
||||
{ return N ## _vec_rscan_by_ ## NK(vec__tmp, key__tmp); }\
|
||||
static inline size_t N ## _vec_rscan_ex(N ## _vec_t vec__tmp, size_t begin__tmp, size_t end__tmp, TK key__tmp)\
|
||||
{ return N ## _vec_rscan_ex_by_ ## NK(vec__tmp, begin__tmp, end__tmp, key__tmp); }
|
||||
#define __flatbuffers_define_default_scan_by_string_field(N, NK) \
|
||||
static inline size_t N ## _vec_scan(N ## _vec_t vec__tmp, const char *s__tmp)\
|
||||
{ return N ## _vec_scan_by_ ## NK(vec__tmp, s__tmp); }\
|
||||
static inline size_t N ## _vec_scan_n(N ## _vec_t vec__tmp, const char *s__tmp, size_t n__tmp)\
|
||||
{ return N ## _vec_scan_n_by_ ## NK(vec__tmp, s__tmp, n__tmp); }\
|
||||
static inline size_t N ## _vec_scan_ex(N ## _vec_t vec__tmp, size_t begin__tmp, size_t end__tmp, const char *s__tmp)\
|
||||
{ return N ## _vec_scan_ex_by_ ## NK(vec__tmp, begin__tmp, end__tmp, s__tmp); }\
|
||||
static inline size_t N ## _vec_scan_ex_n(N ## _vec_t vec__tmp, size_t begin__tmp, size_t end__tmp, const char *s__tmp, size_t n__tmp)\
|
||||
{ return N ## _vec_scan_ex_n_by_ ## NK(vec__tmp, begin__tmp, end__tmp, s__tmp, n__tmp); }\
|
||||
static inline size_t N ## _vec_rscan(N ## _vec_t vec__tmp, const char *s__tmp)\
|
||||
{ return N ## _vec_rscan_by_ ## NK(vec__tmp, s__tmp); }\
|
||||
static inline size_t N ## _vec_rscan_n(N ## _vec_t vec__tmp, const char *s__tmp, size_t n__tmp)\
|
||||
{ return N ## _vec_rscan_n_by_ ## NK(vec__tmp, s__tmp, n__tmp); }\
|
||||
static inline size_t N ## _vec_rscan_ex(N ## _vec_t vec__tmp, size_t begin__tmp, size_t end__tmp, const char *s__tmp)\
|
||||
{ return N ## _vec_rscan_ex_by_ ## NK(vec__tmp, begin__tmp, end__tmp, s__tmp); }\
|
||||
static inline size_t N ## _vec_rscan_ex_n(N ## _vec_t vec__tmp, size_t begin__tmp, size_t end__tmp, const char *s__tmp, size_t n__tmp)\
|
||||
{ return N ## _vec_rscan_ex_n_by_ ## NK(vec__tmp, begin__tmp, end__tmp, s__tmp, n__tmp); }
|
||||
#define __flatbuffers_heap_sort(N, X, A, E, L, TK, TE, D, S)\
|
||||
static inline void __ ## N ## X ## __heap_sift_down(\
|
||||
N ## _mutable_vec_t vec__tmp, size_t start__tmp, size_t end__tmp)\
|
||||
{ size_t child__tmp, root__tmp; TK v1__tmp, v2__tmp, vroot__tmp;\
|
||||
root__tmp = start__tmp;\
|
||||
while ((root__tmp << 1) <= end__tmp) {\
|
||||
child__tmp = root__tmp << 1;\
|
||||
if (child__tmp < end__tmp) {\
|
||||
v1__tmp = A(E(vec__tmp, child__tmp));\
|
||||
v2__tmp = A(E(vec__tmp, child__tmp + 1));\
|
||||
if (D(v1__tmp, v2__tmp) < 0) {\
|
||||
child__tmp++;\
|
||||
}\
|
||||
}\
|
||||
vroot__tmp = A(E(vec__tmp, root__tmp));\
|
||||
v1__tmp = A(E(vec__tmp, child__tmp));\
|
||||
if (D(vroot__tmp, v1__tmp) < 0) {\
|
||||
S(vec__tmp, root__tmp, child__tmp, TE);\
|
||||
root__tmp = child__tmp;\
|
||||
} else {\
|
||||
return;\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
static inline void __ ## N ## X ## __heap_sort(N ## _mutable_vec_t vec__tmp)\
|
||||
{ size_t start__tmp, end__tmp, size__tmp;\
|
||||
size__tmp = L(vec__tmp); if (size__tmp == 0) return; end__tmp = size__tmp - 1; start__tmp = size__tmp >> 1;\
|
||||
do { __ ## N ## X ## __heap_sift_down(vec__tmp, start__tmp, end__tmp); } while (start__tmp--);\
|
||||
while (end__tmp > 0) { \
|
||||
S(vec__tmp, 0, end__tmp, TE);\
|
||||
__ ## N ## X ## __heap_sift_down(vec__tmp, 0, --end__tmp); } }
|
||||
#define __flatbuffers_define_sort_by_field(N, NK, TK, TE, D, S)\
|
||||
__flatbuffers_heap_sort(N, _sort_by_ ## NK, N ## _ ## NK ## _get, N ## _vec_at, N ## _vec_len, TK, TE, D, S)\
|
||||
static inline void N ## _vec_sort_by_ ## NK(N ## _mutable_vec_t vec__tmp)\
|
||||
{ __ ## N ## _sort_by_ ## NK ## __heap_sort(vec__tmp); }
|
||||
#define __flatbuffers_define_sort(N, TK, TE, D, S)\
|
||||
__flatbuffers_heap_sort(N, , __flatbuffers_identity, N ## _vec_at, N ## _vec_len, TK, TE, D, S)\
|
||||
static inline void N ## _vec_sort(N ## _mutable_vec_t vec__tmp) { __ ## N ## __heap_sort(vec__tmp); }
|
||||
#define __flatbuffers_scalar_diff(x, y) ((x) < (y) ? -1 : (x) > (y))
|
||||
#define __flatbuffers_string_diff(x, y) __flatbuffers_string_n_cmp((x), (const char *)(y), flatbuffers_string_len(y))
|
||||
#define __flatbuffers_value_swap(vec, a, b, TE) { TE x__tmp = vec[b]; vec[b] = vec[a]; vec[a] = x__tmp; }
|
||||
#define __flatbuffers_uoffset_swap(vec, a, b, TE)\
|
||||
{ TE ta__tmp, tb__tmp, d__tmp;\
|
||||
d__tmp = (TE)((a - b) * sizeof(vec[0]));\
|
||||
ta__tmp = __flatbuffers_uoffset_read_from_pe(vec + b) - d__tmp;\
|
||||
tb__tmp = __flatbuffers_uoffset_read_from_pe(vec + a) + d__tmp;\
|
||||
__flatbuffers_uoffset_write_to_pe(vec + a, ta__tmp);\
|
||||
__flatbuffers_uoffset_write_to_pe(vec + b, tb__tmp); }
|
||||
#define __flatbuffers_scalar_swap(vec, a, b, TE) __flatbuffers_value_swap(vec, a, b, TE)
|
||||
#define __flatbuffers_string_swap(vec, a, b, TE) __flatbuffers_uoffset_swap(vec, a, b, TE)
|
||||
#define __flatbuffers_struct_swap(vec, a, b, TE) __flatbuffers_value_swap(vec, a, b, TE)
|
||||
#define __flatbuffers_table_swap(vec, a, b, TE) __flatbuffers_uoffset_swap(vec, a, b, TE)
|
||||
#define __flatbuffers_define_struct_sort_by_scalar_field(N, NK, TK, TE)\
|
||||
__flatbuffers_define_sort_by_field(N, NK, TK, TE, __flatbuffers_scalar_diff, __flatbuffers_struct_swap)
|
||||
#define __flatbuffers_define_table_sort_by_scalar_field(N, NK, TK)\
|
||||
__flatbuffers_define_sort_by_field(N, NK, TK, flatbuffers_uoffset_t, __flatbuffers_scalar_diff, __flatbuffers_table_swap)
|
||||
#define __flatbuffers_define_table_sort_by_string_field(N, NK)\
|
||||
__flatbuffers_define_sort_by_field(N, NK, flatbuffers_string_t, flatbuffers_uoffset_t, __flatbuffers_string_diff, __flatbuffers_table_swap)
|
||||
#define __flatbuffers_define_scalar_sort(N, T) __flatbuffers_define_sort(N, T, T, __flatbuffers_scalar_diff, __flatbuffers_scalar_swap)
|
||||
#define __flatbuffers_define_string_sort() __flatbuffers_define_sort(flatbuffers_string, flatbuffers_string_t, flatbuffers_uoffset_t, __flatbuffers_string_diff, __flatbuffers_string_swap)
|
||||
#define __flatbuffers_sort_vector_field(N, NK, T, t)\
|
||||
{ T ## _mutable_vec_t v__tmp = (T ## _mutable_vec_t) N ## _ ## NK ## _get(t);\
|
||||
if (v__tmp) T ## _vec_sort(v__tmp); }
|
||||
#define __flatbuffers_sort_table_field(N, NK, T, t)\
|
||||
{ T ## _sort((T ## _mutable_table_t)N ## _ ## NK ## _get(t)); }
|
||||
#define __flatbuffers_sort_union_field(N, NK, T, t)\
|
||||
{ T ## _sort(T ## _mutable_union_cast(N ## _ ## NK ## _union(t))); }
|
||||
#define __flatbuffers_sort_table_vector_field_elements(N, NK, T, t)\
|
||||
{ T ## _vec_t v__tmp = N ## _ ## NK ## _get(t); size_t i__tmp, n__tmp;\
|
||||
n__tmp = T ## _vec_len(v__tmp); for (i__tmp = 0; i__tmp < n__tmp; ++i__tmp) {\
|
||||
T ## _sort((T ## _mutable_table_t)T ## _vec_at(v__tmp, i__tmp)); }}
|
||||
#define __flatbuffers_sort_union_vector_field_elements(N, NK, T, t)\
|
||||
{ T ## _union_vec_t v__tmp = N ## _ ## NK ## _union(t); size_t i__tmp, n__tmp;\
|
||||
n__tmp = T ## _union_vec_len(v__tmp); for (i__tmp = 0; i__tmp < n__tmp; ++i__tmp) {\
|
||||
T ## _sort(T ## _mutable_union_cast(T ## _union_vec_at(v__tmp, i__tmp))); }}
|
||||
#define __flatbuffers_define_scalar_vector(N, T)\
|
||||
typedef const T *N ## _vec_t;\
|
||||
typedef T *N ## _mutable_vec_t;\
|
||||
__flatbuffers_define_scalar_vec_len(N)\
|
||||
__flatbuffers_define_scalar_vec_at(N, T)\
|
||||
__flatbuffers_define_scalar_find(N, T)\
|
||||
__flatbuffers_define_scalar_scan(N, T)\
|
||||
__flatbuffers_define_scalar_sort(N, T)
|
||||
|
||||
#define __flatbuffers_define_integer_type(N, T, W)\
|
||||
__flatcc_define_integer_accessors(N, T, W, flatbuffers_endian)\
|
||||
__flatbuffers_define_scalar_vector(N, T)
|
||||
__flatbuffers_define_scalar_vector(flatbuffers_bool, flatbuffers_bool_t)
|
||||
__flatbuffers_define_scalar_vector(flatbuffers_char, char)
|
||||
__flatbuffers_define_scalar_vector(flatbuffers_uint8, uint8_t)
|
||||
__flatbuffers_define_scalar_vector(flatbuffers_int8, int8_t)
|
||||
__flatbuffers_define_scalar_vector(flatbuffers_uint16, uint16_t)
|
||||
__flatbuffers_define_scalar_vector(flatbuffers_int16, int16_t)
|
||||
__flatbuffers_define_scalar_vector(flatbuffers_uint32, uint32_t)
|
||||
__flatbuffers_define_scalar_vector(flatbuffers_int32, int32_t)
|
||||
__flatbuffers_define_scalar_vector(flatbuffers_uint64, uint64_t)
|
||||
__flatbuffers_define_scalar_vector(flatbuffers_int64, int64_t)
|
||||
__flatbuffers_define_scalar_vector(flatbuffers_float, float)
|
||||
__flatbuffers_define_scalar_vector(flatbuffers_double, double)
|
||||
__flatbuffers_define_scalar_vector(flatbuffers_union_type, flatbuffers_union_type_t)
|
||||
static inline size_t flatbuffers_string_vec_find(flatbuffers_string_vec_t vec, const char *s)
|
||||
__flatbuffers_find_by_string_field(__flatbuffers_identity, vec, flatbuffers_string_vec_at, flatbuffers_string_vec_len, s)
|
||||
static inline size_t flatbuffers_string_vec_find_n(flatbuffers_string_vec_t vec, const char *s, size_t n)
|
||||
__flatbuffers_find_by_string_n_field(__flatbuffers_identity, vec, flatbuffers_string_vec_at, flatbuffers_string_vec_len, s, n)
|
||||
static inline size_t flatbuffers_string_vec_scan(flatbuffers_string_vec_t vec, const char *s)
|
||||
__flatbuffers_scan_by_string_field(0, flatbuffers_string_vec_len(vec), __flatbuffers_identity, vec, flatbuffers_string_vec_at, flatbuffers_string_vec_len, s)
|
||||
static inline size_t flatbuffers_string_vec_scan_n(flatbuffers_string_vec_t vec, const char *s, size_t n)
|
||||
__flatbuffers_scan_by_string_n_field(0, flatbuffers_string_vec_len(vec), __flatbuffers_identity, vec, flatbuffers_string_vec_at, flatbuffers_string_vec_len, s, n)
|
||||
static inline size_t flatbuffers_string_vec_scan_ex(flatbuffers_string_vec_t vec, size_t begin, size_t end, const char *s)
|
||||
__flatbuffers_scan_by_string_field(begin, __flatbuffers_min(end, flatbuffers_string_vec_len(vec)), __flatbuffers_identity, vec, flatbuffers_string_vec_at, flatbuffers_string_vec_len, s)
|
||||
static inline size_t flatbuffers_string_vec_scan_ex_n(flatbuffers_string_vec_t vec, size_t begin, size_t end, const char *s, size_t n)
|
||||
__flatbuffers_scan_by_string_n_field(begin, __flatbuffers_min(end, flatbuffers_string_vec_len(vec)), __flatbuffers_identity, vec, flatbuffers_string_vec_at, flatbuffers_string_vec_len, s, n)
|
||||
static inline size_t flatbuffers_string_vec_rscan(flatbuffers_string_vec_t vec, const char *s)
|
||||
__flatbuffers_rscan_by_string_field(0, flatbuffers_string_vec_len(vec), __flatbuffers_identity, vec, flatbuffers_string_vec_at, flatbuffers_string_vec_len, s)
|
||||
static inline size_t flatbuffers_string_vec_rscan_n(flatbuffers_string_vec_t vec, const char *s, size_t n)
|
||||
__flatbuffers_rscan_by_string_n_field(0, flatbuffers_string_vec_len(vec), __flatbuffers_identity, vec, flatbuffers_string_vec_at, flatbuffers_string_vec_len, s, n)
|
||||
static inline size_t flatbuffers_string_vec_rscan_ex(flatbuffers_string_vec_t vec, size_t begin, size_t end, const char *s)
|
||||
__flatbuffers_rscan_by_string_field(begin, __flatbuffers_min(end, flatbuffers_string_vec_len(vec)), __flatbuffers_identity, vec, flatbuffers_string_vec_at, flatbuffers_string_vec_len, s)
|
||||
static inline size_t flatbuffers_string_vec_rscan_ex_n(flatbuffers_string_vec_t vec, size_t begin, size_t end, const char *s, size_t n)
|
||||
__flatbuffers_rscan_by_string_n_field(begin, __flatbuffers_min(end, flatbuffers_string_vec_len(vec)), __flatbuffers_identity, vec, flatbuffers_string_vec_at, flatbuffers_string_vec_len, s, n)
|
||||
__flatbuffers_define_string_sort()
|
||||
#define __flatbuffers_define_struct_scalar_fixed_array_field(N, NK, TK, T, L)\
|
||||
static inline T N ## _ ## NK ## _get(N ## _struct_t t__tmp, size_t i__tmp)\
|
||||
{ if (!t__tmp || i__tmp >= L) return 0;\
|
||||
return __flatbuffers_read_scalar(TK, &(t__tmp->NK[i__tmp])); }\
|
||||
static inline const T *N ## _ ## NK ## _get_ptr(N ## _struct_t t__tmp)\
|
||||
{ return t__tmp ? t__tmp->NK : 0; }\
|
||||
static inline size_t N ## _ ## NK ## _get_len(void) { return L; }\
|
||||
static inline T N ## _ ## NK (N ## _struct_t t__tmp, size_t i__tmp)\
|
||||
{ return N ## _ ## NK ## _get(t__tmp, i__tmp); }
|
||||
#define __flatbuffers_define_struct_struct_fixed_array_field(N, NK, T, L)\
|
||||
static inline T N ## _ ## NK ## _get(N ## _struct_t t__tmp, size_t i__tmp)\
|
||||
{ if (!t__tmp || i__tmp >= L) return 0; return t__tmp->NK + i__tmp; }static inline T N ## _ ## NK ## _get_ptr(N ## _struct_t t__tmp)\
|
||||
{ return t__tmp ? t__tmp->NK : 0; }\
|
||||
static inline size_t N ## _ ## NK ## _get_len(void) { return L; }\
|
||||
static inline T N ## _ ## NK(N ## _struct_t t__tmp, size_t i__tmp)\
|
||||
{ if (!t__tmp || i__tmp >= L) return 0; return t__tmp->NK + i__tmp; }
|
||||
#define __flatbuffers_define_struct_scalar_field(N, NK, TK, T)\
|
||||
static inline T N ## _ ## NK ## _get(N ## _struct_t t__tmp)\
|
||||
{ return t__tmp ? __flatbuffers_read_scalar(TK, &(t__tmp->NK)) : 0; }\
|
||||
static inline const T *N ## _ ## NK ## _get_ptr(N ## _struct_t t__tmp)\
|
||||
{ return t__tmp ? &(t__tmp->NK) : 0; }\
|
||||
static inline T N ## _ ## NK (N ## _struct_t t__tmp)\
|
||||
{ return t__tmp ? __flatbuffers_read_scalar(TK, &(t__tmp->NK)) : 0; }\
|
||||
__flatbuffers_define_scan_by_scalar_field(N, NK, T)
|
||||
#define __flatbuffers_define_struct_struct_field(N, NK, T)\
|
||||
static inline T N ## _ ## NK ## _get(N ## _struct_t t__tmp) { return t__tmp ? &(t__tmp->NK) : 0; }\
|
||||
static inline T N ## _ ## NK (N ## _struct_t t__tmp) { return t__tmp ? &(t__tmp->NK) : 0; }
|
||||
/* If fid is null, the function returns true without testing as buffer is not expected to have any id. */
|
||||
static inline int flatbuffers_has_identifier(const void *buffer, const char *fid)
|
||||
{ flatbuffers_thash_t id, id2 = 0; if (fid == 0) { return 1; };
|
||||
id2 = flatbuffers_type_hash_from_string(fid);
|
||||
id = __flatbuffers_thash_read_from_pe(((flatbuffers_uoffset_t *)buffer) + 1);
|
||||
return id2 == 0 || id == id2; }
|
||||
static inline int flatbuffers_has_type_hash(const void *buffer, flatbuffers_thash_t thash)
|
||||
{ return thash == 0 || (__flatbuffers_thash_read_from_pe((flatbuffers_uoffset_t *)buffer + 1) == thash); }
|
||||
|
||||
static inline flatbuffers_thash_t flatbuffers_get_type_hash(const void *buffer)
|
||||
{ return __flatbuffers_thash_read_from_pe((flatbuffers_uoffset_t *)buffer + 1); }
|
||||
|
||||
#define flatbuffers_verify_endian() flatbuffers_has_identifier("\x00\x00\x00\x00" "1234", "1234")
|
||||
static inline void *flatbuffers_read_size_prefix(void *b, size_t *size_out)
|
||||
{ if (size_out) { *size_out = (size_t)__flatbuffers_uoffset_read_from_pe(b); }
|
||||
return (uint8_t *)b + sizeof(flatbuffers_uoffset_t); }
|
||||
/* Null file identifier accepts anything, otherwise fid should be 4 characters. */
|
||||
#define __flatbuffers_read_root(T, K, buffer, fid)\
|
||||
((!buffer || !flatbuffers_has_identifier(buffer, fid)) ? 0 :\
|
||||
((T ## _ ## K ## t)(((uint8_t *)buffer) +\
|
||||
__flatbuffers_uoffset_read_from_pe(buffer))))
|
||||
#define __flatbuffers_read_typed_root(T, K, buffer, thash)\
|
||||
((!buffer || !flatbuffers_has_type_hash(buffer, thash)) ? 0 :\
|
||||
((T ## _ ## K ## t)(((uint8_t *)buffer) +\
|
||||
__flatbuffers_uoffset_read_from_pe(buffer))))
|
||||
#define __flatbuffers_nested_buffer_as_root(C, N, T, K)\
|
||||
static inline T ## _ ## K ## t C ## _ ## N ## _as_root_with_identifier(C ## _ ## table_t t__tmp, const char *fid__tmp)\
|
||||
{ const uint8_t *buffer__tmp = C ## _ ## N(t__tmp); return __flatbuffers_read_root(T, K, buffer__tmp, fid__tmp); }\
|
||||
static inline T ## _ ## K ## t C ## _ ## N ## _as_typed_root(C ## _ ## table_t t__tmp)\
|
||||
{ const uint8_t *buffer__tmp = C ## _ ## N(t__tmp); return __flatbuffers_read_root(T, K, buffer__tmp, C ## _ ## type_identifier); }\
|
||||
static inline T ## _ ## K ## t C ## _ ## N ## _as_root(C ## _ ## table_t t__tmp)\
|
||||
{ const char *fid__tmp = T ## _file_identifier;\
|
||||
const uint8_t *buffer__tmp = C ## _ ## N(t__tmp); return __flatbuffers_read_root(T, K, buffer__tmp, fid__tmp); }
|
||||
#define __flatbuffers_buffer_as_root(N, K)\
|
||||
static inline N ## _ ## K ## t N ## _as_root_with_identifier(const void *buffer__tmp, const char *fid__tmp)\
|
||||
{ return __flatbuffers_read_root(N, K, buffer__tmp, fid__tmp); }\
|
||||
static inline N ## _ ## K ## t N ## _as_root_with_type_hash(const void *buffer__tmp, flatbuffers_thash_t thash__tmp)\
|
||||
{ return __flatbuffers_read_typed_root(N, K, buffer__tmp, thash__tmp); }\
|
||||
static inline N ## _ ## K ## t N ## _as_root(const void *buffer__tmp)\
|
||||
{ const char *fid__tmp = N ## _file_identifier;\
|
||||
return __flatbuffers_read_root(N, K, buffer__tmp, fid__tmp); }\
|
||||
static inline N ## _ ## K ## t N ## _as_typed_root(const void *buffer__tmp)\
|
||||
{ return __flatbuffers_read_typed_root(N, K, buffer__tmp, N ## _type_hash); }
|
||||
#define __flatbuffers_struct_as_root(N) __flatbuffers_buffer_as_root(N, struct_)
|
||||
#define __flatbuffers_table_as_root(N) __flatbuffers_buffer_as_root(N, table_)
|
||||
|
||||
#include "flatcc/flatcc_epilogue.h"
|
||||
#endif /* FLATBUFFERS_COMMON_H */
|
||||
69
nostrdb/src/bindings/c/meta_builder.h
Normal file
69
nostrdb/src/bindings/c/meta_builder.h
Normal file
@@ -0,0 +1,69 @@
|
||||
#ifndef META_BUILDER_H
|
||||
#define META_BUILDER_H
|
||||
|
||||
/* Generated by flatcc 0.6.1 FlatBuffers schema compiler for C by dvide.com */
|
||||
|
||||
#ifndef META_READER_H
|
||||
#include "meta_reader.h"
|
||||
#endif
|
||||
#ifndef FLATBUFFERS_COMMON_BUILDER_H
|
||||
#include "flatbuffers_common_builder.h"
|
||||
#endif
|
||||
#include "flatcc/flatcc_prologue.h"
|
||||
#ifndef flatbuffers_identifier
|
||||
#define flatbuffers_identifier 0
|
||||
#endif
|
||||
#ifndef flatbuffers_extension
|
||||
#define flatbuffers_extension "bin"
|
||||
#endif
|
||||
|
||||
static const flatbuffers_voffset_t __NdbEventMeta_required[] = { 0 };
|
||||
typedef flatbuffers_ref_t NdbEventMeta_ref_t;
|
||||
static NdbEventMeta_ref_t NdbEventMeta_clone(flatbuffers_builder_t *B, NdbEventMeta_table_t t);
|
||||
__flatbuffers_build_table(flatbuffers_, NdbEventMeta, 6)
|
||||
|
||||
#define __NdbEventMeta_formal_args ,\
|
||||
int32_t v0, int32_t v1, int32_t v2, int32_t v3, int32_t v4, int64_t v5
|
||||
#define __NdbEventMeta_call_args ,\
|
||||
v0, v1, v2, v3, v4, v5
|
||||
static inline NdbEventMeta_ref_t NdbEventMeta_create(flatbuffers_builder_t *B __NdbEventMeta_formal_args);
|
||||
__flatbuffers_build_table_prolog(flatbuffers_, NdbEventMeta, NdbEventMeta_file_identifier, NdbEventMeta_type_identifier)
|
||||
|
||||
__flatbuffers_build_scalar_field(0, flatbuffers_, NdbEventMeta_received_at, flatbuffers_int32, int32_t, 4, 4, INT32_C(0), NdbEventMeta)
|
||||
__flatbuffers_build_scalar_field(1, flatbuffers_, NdbEventMeta_reactions, flatbuffers_int32, int32_t, 4, 4, INT32_C(0), NdbEventMeta)
|
||||
__flatbuffers_build_scalar_field(2, flatbuffers_, NdbEventMeta_quotes, flatbuffers_int32, int32_t, 4, 4, INT32_C(0), NdbEventMeta)
|
||||
__flatbuffers_build_scalar_field(3, flatbuffers_, NdbEventMeta_reposts, flatbuffers_int32, int32_t, 4, 4, INT32_C(0), NdbEventMeta)
|
||||
__flatbuffers_build_scalar_field(4, flatbuffers_, NdbEventMeta_zaps, flatbuffers_int32, int32_t, 4, 4, INT32_C(0), NdbEventMeta)
|
||||
__flatbuffers_build_scalar_field(5, flatbuffers_, NdbEventMeta_zap_total, flatbuffers_int64, int64_t, 8, 8, INT64_C(0), NdbEventMeta)
|
||||
|
||||
static inline NdbEventMeta_ref_t NdbEventMeta_create(flatbuffers_builder_t *B __NdbEventMeta_formal_args)
|
||||
{
|
||||
if (NdbEventMeta_start(B)
|
||||
|| NdbEventMeta_zap_total_add(B, v5)
|
||||
|| NdbEventMeta_received_at_add(B, v0)
|
||||
|| NdbEventMeta_reactions_add(B, v1)
|
||||
|| NdbEventMeta_quotes_add(B, v2)
|
||||
|| NdbEventMeta_reposts_add(B, v3)
|
||||
|| NdbEventMeta_zaps_add(B, v4)) {
|
||||
return 0;
|
||||
}
|
||||
return NdbEventMeta_end(B);
|
||||
}
|
||||
|
||||
static NdbEventMeta_ref_t NdbEventMeta_clone(flatbuffers_builder_t *B, NdbEventMeta_table_t t)
|
||||
{
|
||||
__flatbuffers_memoize_begin(B, t);
|
||||
if (NdbEventMeta_start(B)
|
||||
|| NdbEventMeta_zap_total_pick(B, t)
|
||||
|| NdbEventMeta_received_at_pick(B, t)
|
||||
|| NdbEventMeta_reactions_pick(B, t)
|
||||
|| NdbEventMeta_quotes_pick(B, t)
|
||||
|| NdbEventMeta_reposts_pick(B, t)
|
||||
|| NdbEventMeta_zaps_pick(B, t)) {
|
||||
return 0;
|
||||
}
|
||||
__flatbuffers_memoize_end(B, t, NdbEventMeta_end(B));
|
||||
}
|
||||
|
||||
#include "flatcc/flatcc_epilogue.h"
|
||||
#endif /* META_BUILDER_H */
|
||||
250
nostrdb/src/bindings/c/meta_json_parser.h
Normal file
250
nostrdb/src/bindings/c/meta_json_parser.h
Normal file
@@ -0,0 +1,250 @@
|
||||
#ifndef META_JSON_PARSER_H
|
||||
#define META_JSON_PARSER_H
|
||||
|
||||
/* Generated by flatcc 0.6.1 FlatBuffers schema compiler for C by dvide.com */
|
||||
|
||||
#include "flatcc/flatcc_json_parser.h"
|
||||
#include "flatcc/flatcc_prologue.h"
|
||||
|
||||
/*
|
||||
* Parses the default root table or struct of the schema and constructs a FlatBuffer.
|
||||
*
|
||||
* Builder `B` must be initialized. `ctx` can be null but will hold
|
||||
* hold detailed error info on return when available.
|
||||
* Returns 0 on success, or error code.
|
||||
* `flags` : 0 by default, `flatcc_json_parser_f_skip_unknown` silently
|
||||
* ignores unknown table and structs fields, and union types.
|
||||
*/
|
||||
static int meta_parse_json(flatcc_builder_t *B, flatcc_json_parser_t *ctx,
|
||||
const char *buf, size_t bufsiz, int flags);
|
||||
|
||||
static const char *NdbEventMeta_parse_json_table(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result);
|
||||
static const char *meta_local_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end,
|
||||
int *value_type, uint64_t *value, int *aggregate);
|
||||
static const char *meta_global_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end,
|
||||
int *value_type, uint64_t *value, int *aggregate);
|
||||
|
||||
static const char *NdbEventMeta_parse_json_table(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result)
|
||||
{
|
||||
int more;
|
||||
void *pval;
|
||||
flatcc_builder_ref_t ref, *pref;
|
||||
const char *mark;
|
||||
uint64_t w;
|
||||
|
||||
*result = 0;
|
||||
if (flatcc_builder_start_table(ctx->ctx, 6)) goto failed;
|
||||
buf = flatcc_json_parser_object_start(ctx, buf, end, &more);
|
||||
while (more) {
|
||||
buf = flatcc_json_parser_symbol_start(ctx, buf, end);
|
||||
w = flatcc_json_parser_symbol_part(buf, end);
|
||||
if (w < 0x7265636569766564) { /* branch "received" */
|
||||
if ((w & 0xffffffffffff0000) == 0x71756f7465730000) { /* "quotes" */
|
||||
buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 6);
|
||||
if (mark != buf) {
|
||||
int32_t val = 0;
|
||||
static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = {
|
||||
meta_local_json_parser_enum,
|
||||
meta_global_json_parser_enum, 0 };
|
||||
buf = flatcc_json_parser_int32(ctx, (mark = buf), end, &val);
|
||||
if (mark == buf) {
|
||||
buf = flatcc_json_parser_symbolic_int32(ctx, (mark = buf), end, symbolic_parsers, &val);
|
||||
if (buf == mark || buf == end) goto failed;
|
||||
}
|
||||
if (val != INT32_C(0) || (ctx->flags & flatcc_json_parser_f_force_add)) {
|
||||
if (!(pval = flatcc_builder_table_add(ctx->ctx, 2, 4, 4))) goto failed;
|
||||
flatbuffers_int32_write_to_pe(pval, val);
|
||||
}
|
||||
} else {
|
||||
goto pfguard1;
|
||||
}
|
||||
} else { /* "quotes" */
|
||||
goto pfguard1;
|
||||
} /* "quotes" */
|
||||
goto endpfguard1;
|
||||
pfguard1:
|
||||
if (w == 0x7265616374696f6e) { /* descend "reaction" */
|
||||
buf += 8;
|
||||
w = flatcc_json_parser_symbol_part(buf, end);
|
||||
if ((w & 0xff00000000000000) == 0x7300000000000000) { /* "s" */
|
||||
buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 1);
|
||||
if (mark != buf) {
|
||||
int32_t val = 0;
|
||||
static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = {
|
||||
meta_local_json_parser_enum,
|
||||
meta_global_json_parser_enum, 0 };
|
||||
buf = flatcc_json_parser_int32(ctx, (mark = buf), end, &val);
|
||||
if (mark == buf) {
|
||||
buf = flatcc_json_parser_symbolic_int32(ctx, (mark = buf), end, symbolic_parsers, &val);
|
||||
if (buf == mark || buf == end) goto failed;
|
||||
}
|
||||
if (val != INT32_C(0) || (ctx->flags & flatcc_json_parser_f_force_add)) {
|
||||
if (!(pval = flatcc_builder_table_add(ctx->ctx, 1, 4, 4))) goto failed;
|
||||
flatbuffers_int32_write_to_pe(pval, val);
|
||||
}
|
||||
} else {
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
}
|
||||
} else { /* "s" */
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
} /* "s" */
|
||||
} else { /* descend "reaction" */
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
} /* descend "reaction" */
|
||||
endpfguard1:
|
||||
(void)0;
|
||||
} else { /* branch "received" */
|
||||
if (w < 0x7265706f73747300) { /* branch "reposts" */
|
||||
if (w == 0x7265636569766564) { /* descend "received" */
|
||||
buf += 8;
|
||||
w = flatcc_json_parser_symbol_part(buf, end);
|
||||
if ((w & 0xffffff0000000000) == 0x5f61740000000000) { /* "_at" */
|
||||
buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 3);
|
||||
if (mark != buf) {
|
||||
int32_t val = 0;
|
||||
static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = {
|
||||
meta_local_json_parser_enum,
|
||||
meta_global_json_parser_enum, 0 };
|
||||
buf = flatcc_json_parser_int32(ctx, (mark = buf), end, &val);
|
||||
if (mark == buf) {
|
||||
buf = flatcc_json_parser_symbolic_int32(ctx, (mark = buf), end, symbolic_parsers, &val);
|
||||
if (buf == mark || buf == end) goto failed;
|
||||
}
|
||||
if (val != INT32_C(0) || (ctx->flags & flatcc_json_parser_f_force_add)) {
|
||||
if (!(pval = flatcc_builder_table_add(ctx->ctx, 0, 4, 4))) goto failed;
|
||||
flatbuffers_int32_write_to_pe(pval, val);
|
||||
}
|
||||
} else {
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
}
|
||||
} else { /* "_at" */
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
} /* "_at" */
|
||||
} else { /* descend "received" */
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
} /* descend "received" */
|
||||
} else { /* branch "reposts" */
|
||||
if (w < 0x7a61705f746f7461) { /* branch "zap_tota" */
|
||||
if ((w & 0xffffffffffffff00) == 0x7265706f73747300) { /* "reposts" */
|
||||
buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 7);
|
||||
if (mark != buf) {
|
||||
int32_t val = 0;
|
||||
static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = {
|
||||
meta_local_json_parser_enum,
|
||||
meta_global_json_parser_enum, 0 };
|
||||
buf = flatcc_json_parser_int32(ctx, (mark = buf), end, &val);
|
||||
if (mark == buf) {
|
||||
buf = flatcc_json_parser_symbolic_int32(ctx, (mark = buf), end, symbolic_parsers, &val);
|
||||
if (buf == mark || buf == end) goto failed;
|
||||
}
|
||||
if (val != INT32_C(0) || (ctx->flags & flatcc_json_parser_f_force_add)) {
|
||||
if (!(pval = flatcc_builder_table_add(ctx->ctx, 3, 4, 4))) goto failed;
|
||||
flatbuffers_int32_write_to_pe(pval, val);
|
||||
}
|
||||
} else {
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
}
|
||||
} else { /* "reposts" */
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
} /* "reposts" */
|
||||
} else { /* branch "zap_tota" */
|
||||
if (w == 0x7a61705f746f7461) { /* descend "zap_tota" */
|
||||
buf += 8;
|
||||
w = flatcc_json_parser_symbol_part(buf, end);
|
||||
if ((w & 0xff00000000000000) == 0x6c00000000000000) { /* "l" */
|
||||
buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 1);
|
||||
if (mark != buf) {
|
||||
int64_t val = 0;
|
||||
static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = {
|
||||
meta_local_json_parser_enum,
|
||||
meta_global_json_parser_enum, 0 };
|
||||
buf = flatcc_json_parser_int64(ctx, (mark = buf), end, &val);
|
||||
if (mark == buf) {
|
||||
buf = flatcc_json_parser_symbolic_int64(ctx, (mark = buf), end, symbolic_parsers, &val);
|
||||
if (buf == mark || buf == end) goto failed;
|
||||
}
|
||||
if (val != INT64_C(0) || (ctx->flags & flatcc_json_parser_f_force_add)) {
|
||||
if (!(pval = flatcc_builder_table_add(ctx->ctx, 5, 8, 8))) goto failed;
|
||||
flatbuffers_int64_write_to_pe(pval, val);
|
||||
}
|
||||
} else {
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
}
|
||||
} else { /* "l" */
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
} /* "l" */
|
||||
} else { /* descend "zap_tota" */
|
||||
if ((w & 0xffffffff00000000) == 0x7a61707300000000) { /* "zaps" */
|
||||
buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 4);
|
||||
if (mark != buf) {
|
||||
int32_t val = 0;
|
||||
static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = {
|
||||
meta_local_json_parser_enum,
|
||||
meta_global_json_parser_enum, 0 };
|
||||
buf = flatcc_json_parser_int32(ctx, (mark = buf), end, &val);
|
||||
if (mark == buf) {
|
||||
buf = flatcc_json_parser_symbolic_int32(ctx, (mark = buf), end, symbolic_parsers, &val);
|
||||
if (buf == mark || buf == end) goto failed;
|
||||
}
|
||||
if (val != INT32_C(0) || (ctx->flags & flatcc_json_parser_f_force_add)) {
|
||||
if (!(pval = flatcc_builder_table_add(ctx->ctx, 4, 4, 4))) goto failed;
|
||||
flatbuffers_int32_write_to_pe(pval, val);
|
||||
}
|
||||
} else {
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
}
|
||||
} else { /* "zaps" */
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
} /* "zaps" */
|
||||
} /* descend "zap_tota" */
|
||||
} /* branch "zap_tota" */
|
||||
} /* branch "reposts" */
|
||||
} /* branch "received" */
|
||||
buf = flatcc_json_parser_object_end(ctx, buf, end, &more);
|
||||
}
|
||||
if (ctx->error) goto failed;
|
||||
if (!(*result = flatcc_builder_end_table(ctx->ctx))) goto failed;
|
||||
return buf;
|
||||
failed:
|
||||
return flatcc_json_parser_set_error(ctx, buf, end, flatcc_json_parser_error_runtime);
|
||||
}
|
||||
|
||||
static inline int NdbEventMeta_parse_json_as_root(flatcc_builder_t *B, flatcc_json_parser_t *ctx, const char *buf, size_t bufsiz, int flags, const char *fid)
|
||||
{
|
||||
return flatcc_json_parser_table_as_root(B, ctx, buf, bufsiz, flags, fid, NdbEventMeta_parse_json_table);
|
||||
}
|
||||
|
||||
static const char *meta_local_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end,
|
||||
int *value_type, uint64_t *value, int *aggregate)
|
||||
{
|
||||
/* Scope has no enum / union types to look up. */
|
||||
return buf; /* unmatched; */
|
||||
}
|
||||
|
||||
static const char *meta_global_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end,
|
||||
int *value_type, uint64_t *value, int *aggregate)
|
||||
{
|
||||
/* Global scope has no enum / union types to look up. */
|
||||
return buf; /* unmatched; */
|
||||
}
|
||||
|
||||
static int meta_parse_json(flatcc_builder_t *B, flatcc_json_parser_t *ctx,
|
||||
const char *buf, size_t bufsiz, int flags)
|
||||
{
|
||||
flatcc_json_parser_t parser;
|
||||
flatcc_builder_ref_t root;
|
||||
|
||||
ctx = ctx ? ctx : &parser;
|
||||
flatcc_json_parser_init(ctx, B, buf, buf + bufsiz, flags);
|
||||
if (flatcc_builder_start_buffer(B, 0, 0, 0)) return -1;
|
||||
NdbEventMeta_parse_json_table(ctx, buf, buf + bufsiz, &root);
|
||||
if (ctx->error) {
|
||||
return ctx->error;
|
||||
}
|
||||
if (!flatcc_builder_end_buffer(B, root)) return -1;
|
||||
ctx->end_loc = buf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "flatcc/flatcc_epilogue.h"
|
||||
#endif /* META_JSON_PARSER_H */
|
||||
58
nostrdb/src/bindings/c/meta_reader.h
Normal file
58
nostrdb/src/bindings/c/meta_reader.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#ifndef META_READER_H
|
||||
#define META_READER_H
|
||||
|
||||
/* Generated by flatcc 0.6.1 FlatBuffers schema compiler for C by dvide.com */
|
||||
|
||||
#ifndef FLATBUFFERS_COMMON_READER_H
|
||||
#include "flatbuffers_common_reader.h"
|
||||
#endif
|
||||
#include "flatcc/flatcc_flatbuffers.h"
|
||||
#ifndef __alignas_is_defined
|
||||
#include <stdalign.h>
|
||||
#endif
|
||||
#include "flatcc/flatcc_prologue.h"
|
||||
#ifndef flatbuffers_identifier
|
||||
#define flatbuffers_identifier 0
|
||||
#endif
|
||||
#ifndef flatbuffers_extension
|
||||
#define flatbuffers_extension "bin"
|
||||
#endif
|
||||
|
||||
|
||||
typedef const struct NdbEventMeta_table *NdbEventMeta_table_t;
|
||||
typedef struct NdbEventMeta_table *NdbEventMeta_mutable_table_t;
|
||||
typedef const flatbuffers_uoffset_t *NdbEventMeta_vec_t;
|
||||
typedef flatbuffers_uoffset_t *NdbEventMeta_mutable_vec_t;
|
||||
#ifndef NdbEventMeta_file_identifier
|
||||
#define NdbEventMeta_file_identifier 0
|
||||
#endif
|
||||
/* deprecated, use NdbEventMeta_file_identifier */
|
||||
#ifndef NdbEventMeta_identifier
|
||||
#define NdbEventMeta_identifier 0
|
||||
#endif
|
||||
#define NdbEventMeta_type_hash ((flatbuffers_thash_t)0xa8c23be8)
|
||||
#define NdbEventMeta_type_identifier "\xe8\x3b\xc2\xa8"
|
||||
#ifndef NdbEventMeta_file_extension
|
||||
#define NdbEventMeta_file_extension "bin"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
struct NdbEventMeta_table { uint8_t unused__; };
|
||||
|
||||
static inline size_t NdbEventMeta_vec_len(NdbEventMeta_vec_t vec)
|
||||
__flatbuffers_vec_len(vec)
|
||||
static inline NdbEventMeta_table_t NdbEventMeta_vec_at(NdbEventMeta_vec_t vec, size_t i)
|
||||
__flatbuffers_offset_vec_at(NdbEventMeta_table_t, vec, i, 0)
|
||||
__flatbuffers_table_as_root(NdbEventMeta)
|
||||
|
||||
__flatbuffers_define_scalar_field(0, NdbEventMeta, received_at, flatbuffers_int32, int32_t, INT32_C(0))
|
||||
__flatbuffers_define_scalar_field(1, NdbEventMeta, reactions, flatbuffers_int32, int32_t, INT32_C(0))
|
||||
__flatbuffers_define_scalar_field(2, NdbEventMeta, quotes, flatbuffers_int32, int32_t, INT32_C(0))
|
||||
__flatbuffers_define_scalar_field(3, NdbEventMeta, reposts, flatbuffers_int32, int32_t, INT32_C(0))
|
||||
__flatbuffers_define_scalar_field(4, NdbEventMeta, zaps, flatbuffers_int32, int32_t, INT32_C(0))
|
||||
__flatbuffers_define_scalar_field(5, NdbEventMeta, zap_total, flatbuffers_int64, int64_t, INT64_C(0))
|
||||
|
||||
|
||||
#include "flatcc/flatcc_epilogue.h"
|
||||
#endif /* META_READER_H */
|
||||
47
nostrdb/src/bindings/c/meta_verifier.h
Normal file
47
nostrdb/src/bindings/c/meta_verifier.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#ifndef META_VERIFIER_H
|
||||
#define META_VERIFIER_H
|
||||
|
||||
/* Generated by flatcc 0.6.1 FlatBuffers schema compiler for C by dvide.com */
|
||||
|
||||
#ifndef META_READER_H
|
||||
#include "meta_reader.h"
|
||||
#endif
|
||||
#include "flatcc/flatcc_verifier.h"
|
||||
#include "flatcc/flatcc_prologue.h"
|
||||
|
||||
static int NdbEventMeta_verify_table(flatcc_table_verifier_descriptor_t *td);
|
||||
|
||||
static int NdbEventMeta_verify_table(flatcc_table_verifier_descriptor_t *td)
|
||||
{
|
||||
int ret;
|
||||
if ((ret = flatcc_verify_field(td, 0, 4, 4) /* received_at */)) return ret;
|
||||
if ((ret = flatcc_verify_field(td, 1, 4, 4) /* reactions */)) return ret;
|
||||
if ((ret = flatcc_verify_field(td, 2, 4, 4) /* quotes */)) return ret;
|
||||
if ((ret = flatcc_verify_field(td, 3, 4, 4) /* reposts */)) return ret;
|
||||
if ((ret = flatcc_verify_field(td, 4, 4, 4) /* zaps */)) return ret;
|
||||
if ((ret = flatcc_verify_field(td, 5, 8, 8) /* zap_total */)) return ret;
|
||||
return flatcc_verify_ok;
|
||||
}
|
||||
|
||||
static inline int NdbEventMeta_verify_as_root(const void *buf, size_t bufsiz)
|
||||
{
|
||||
return flatcc_verify_table_as_root(buf, bufsiz, NdbEventMeta_identifier, &NdbEventMeta_verify_table);
|
||||
}
|
||||
|
||||
static inline int NdbEventMeta_verify_as_typed_root(const void *buf, size_t bufsiz)
|
||||
{
|
||||
return flatcc_verify_table_as_root(buf, bufsiz, NdbEventMeta_type_identifier, &NdbEventMeta_verify_table);
|
||||
}
|
||||
|
||||
static inline int NdbEventMeta_verify_as_root_with_identifier(const void *buf, size_t bufsiz, const char *fid)
|
||||
{
|
||||
return flatcc_verify_table_as_root(buf, bufsiz, fid, &NdbEventMeta_verify_table);
|
||||
}
|
||||
|
||||
static inline int NdbEventMeta_verify_as_root_with_type_hash(const void *buf, size_t bufsiz, flatbuffers_thash_t thash)
|
||||
{
|
||||
return flatcc_verify_table_as_typed_root(buf, bufsiz, thash, &NdbEventMeta_verify_table);
|
||||
}
|
||||
|
||||
#include "flatcc/flatcc_epilogue.h"
|
||||
#endif /* META_VERIFIER_H */
|
||||
131
nostrdb/src/bindings/c/profile_builder.h
Normal file
131
nostrdb/src/bindings/c/profile_builder.h
Normal file
@@ -0,0 +1,131 @@
|
||||
#ifndef PROFILE_BUILDER_H
|
||||
#define PROFILE_BUILDER_H
|
||||
|
||||
/* Generated by flatcc 0.6.1 FlatBuffers schema compiler for C by dvide.com */
|
||||
|
||||
#ifndef PROFILE_READER_H
|
||||
#include "profile_reader.h"
|
||||
#endif
|
||||
#ifndef FLATBUFFERS_COMMON_BUILDER_H
|
||||
#include "flatbuffers_common_builder.h"
|
||||
#endif
|
||||
#include "flatcc/flatcc_prologue.h"
|
||||
#ifndef flatbuffers_identifier
|
||||
#define flatbuffers_identifier 0
|
||||
#endif
|
||||
#ifndef flatbuffers_extension
|
||||
#define flatbuffers_extension "bin"
|
||||
#endif
|
||||
|
||||
static const flatbuffers_voffset_t __NdbProfile_required[] = { 0 };
|
||||
typedef flatbuffers_ref_t NdbProfile_ref_t;
|
||||
static NdbProfile_ref_t NdbProfile_clone(flatbuffers_builder_t *B, NdbProfile_table_t t);
|
||||
__flatbuffers_build_table(flatbuffers_, NdbProfile, 12)
|
||||
|
||||
static const flatbuffers_voffset_t __NdbProfileRecord_required[] = { 0 };
|
||||
typedef flatbuffers_ref_t NdbProfileRecord_ref_t;
|
||||
static NdbProfileRecord_ref_t NdbProfileRecord_clone(flatbuffers_builder_t *B, NdbProfileRecord_table_t t);
|
||||
__flatbuffers_build_table(flatbuffers_, NdbProfileRecord, 4)
|
||||
|
||||
#define __NdbProfile_formal_args ,\
|
||||
flatbuffers_string_ref_t v0, flatbuffers_string_ref_t v1, flatbuffers_string_ref_t v2, flatbuffers_string_ref_t v3,\
|
||||
flatbuffers_string_ref_t v4, flatbuffers_string_ref_t v5, flatbuffers_bool_t v6, flatbuffers_string_ref_t v7,\
|
||||
flatbuffers_string_ref_t v8, int32_t v9, int32_t v10, flatbuffers_string_ref_t v11
|
||||
#define __NdbProfile_call_args ,\
|
||||
v0, v1, v2, v3,\
|
||||
v4, v5, v6, v7,\
|
||||
v8, v9, v10, v11
|
||||
static inline NdbProfile_ref_t NdbProfile_create(flatbuffers_builder_t *B __NdbProfile_formal_args);
|
||||
__flatbuffers_build_table_prolog(flatbuffers_, NdbProfile, NdbProfile_file_identifier, NdbProfile_type_identifier)
|
||||
|
||||
#define __NdbProfileRecord_formal_args , NdbProfile_ref_t v0, uint64_t v1, uint64_t v2, flatbuffers_string_ref_t v3
|
||||
#define __NdbProfileRecord_call_args , v0, v1, v2, v3
|
||||
static inline NdbProfileRecord_ref_t NdbProfileRecord_create(flatbuffers_builder_t *B __NdbProfileRecord_formal_args);
|
||||
__flatbuffers_build_table_prolog(flatbuffers_, NdbProfileRecord, NdbProfileRecord_file_identifier, NdbProfileRecord_type_identifier)
|
||||
|
||||
__flatbuffers_build_string_field(0, flatbuffers_, NdbProfile_name, NdbProfile)
|
||||
__flatbuffers_build_string_field(1, flatbuffers_, NdbProfile_website, NdbProfile)
|
||||
__flatbuffers_build_string_field(2, flatbuffers_, NdbProfile_about, NdbProfile)
|
||||
__flatbuffers_build_string_field(3, flatbuffers_, NdbProfile_lud16, NdbProfile)
|
||||
__flatbuffers_build_string_field(4, flatbuffers_, NdbProfile_banner, NdbProfile)
|
||||
__flatbuffers_build_string_field(5, flatbuffers_, NdbProfile_display_name, NdbProfile)
|
||||
__flatbuffers_build_scalar_field(6, flatbuffers_, NdbProfile_reactions, flatbuffers_bool, flatbuffers_bool_t, 1, 1, UINT8_C(1), NdbProfile)
|
||||
__flatbuffers_build_string_field(7, flatbuffers_, NdbProfile_picture, NdbProfile)
|
||||
__flatbuffers_build_string_field(8, flatbuffers_, NdbProfile_nip05, NdbProfile)
|
||||
__flatbuffers_build_scalar_field(9, flatbuffers_, NdbProfile_damus_donation, flatbuffers_int32, int32_t, 4, 4, INT32_C(0), NdbProfile)
|
||||
__flatbuffers_build_scalar_field(10, flatbuffers_, NdbProfile_damus_donation_v2, flatbuffers_int32, int32_t, 4, 4, INT32_C(0), NdbProfile)
|
||||
__flatbuffers_build_string_field(11, flatbuffers_, NdbProfile_lud06, NdbProfile)
|
||||
|
||||
static inline NdbProfile_ref_t NdbProfile_create(flatbuffers_builder_t *B __NdbProfile_formal_args)
|
||||
{
|
||||
if (NdbProfile_start(B)
|
||||
|| NdbProfile_name_add(B, v0)
|
||||
|| NdbProfile_website_add(B, v1)
|
||||
|| NdbProfile_about_add(B, v2)
|
||||
|| NdbProfile_lud16_add(B, v3)
|
||||
|| NdbProfile_banner_add(B, v4)
|
||||
|| NdbProfile_display_name_add(B, v5)
|
||||
|| NdbProfile_picture_add(B, v7)
|
||||
|| NdbProfile_nip05_add(B, v8)
|
||||
|| NdbProfile_damus_donation_add(B, v9)
|
||||
|| NdbProfile_damus_donation_v2_add(B, v10)
|
||||
|| NdbProfile_lud06_add(B, v11)
|
||||
|| NdbProfile_reactions_add(B, v6)) {
|
||||
return 0;
|
||||
}
|
||||
return NdbProfile_end(B);
|
||||
}
|
||||
|
||||
static NdbProfile_ref_t NdbProfile_clone(flatbuffers_builder_t *B, NdbProfile_table_t t)
|
||||
{
|
||||
__flatbuffers_memoize_begin(B, t);
|
||||
if (NdbProfile_start(B)
|
||||
|| NdbProfile_name_pick(B, t)
|
||||
|| NdbProfile_website_pick(B, t)
|
||||
|| NdbProfile_about_pick(B, t)
|
||||
|| NdbProfile_lud16_pick(B, t)
|
||||
|| NdbProfile_banner_pick(B, t)
|
||||
|| NdbProfile_display_name_pick(B, t)
|
||||
|| NdbProfile_picture_pick(B, t)
|
||||
|| NdbProfile_nip05_pick(B, t)
|
||||
|| NdbProfile_damus_donation_pick(B, t)
|
||||
|| NdbProfile_damus_donation_v2_pick(B, t)
|
||||
|| NdbProfile_lud06_pick(B, t)
|
||||
|| NdbProfile_reactions_pick(B, t)) {
|
||||
return 0;
|
||||
}
|
||||
__flatbuffers_memoize_end(B, t, NdbProfile_end(B));
|
||||
}
|
||||
|
||||
__flatbuffers_build_table_field(0, flatbuffers_, NdbProfileRecord_profile, NdbProfile, NdbProfileRecord)
|
||||
__flatbuffers_build_scalar_field(1, flatbuffers_, NdbProfileRecord_received_at, flatbuffers_uint64, uint64_t, 8, 8, UINT64_C(0), NdbProfileRecord)
|
||||
__flatbuffers_build_scalar_field(2, flatbuffers_, NdbProfileRecord_note_key, flatbuffers_uint64, uint64_t, 8, 8, UINT64_C(0), NdbProfileRecord)
|
||||
__flatbuffers_build_string_field(3, flatbuffers_, NdbProfileRecord_lnurl, NdbProfileRecord)
|
||||
|
||||
static inline NdbProfileRecord_ref_t NdbProfileRecord_create(flatbuffers_builder_t *B __NdbProfileRecord_formal_args)
|
||||
{
|
||||
if (NdbProfileRecord_start(B)
|
||||
|| NdbProfileRecord_received_at_add(B, v1)
|
||||
|| NdbProfileRecord_note_key_add(B, v2)
|
||||
|| NdbProfileRecord_profile_add(B, v0)
|
||||
|| NdbProfileRecord_lnurl_add(B, v3)) {
|
||||
return 0;
|
||||
}
|
||||
return NdbProfileRecord_end(B);
|
||||
}
|
||||
|
||||
static NdbProfileRecord_ref_t NdbProfileRecord_clone(flatbuffers_builder_t *B, NdbProfileRecord_table_t t)
|
||||
{
|
||||
__flatbuffers_memoize_begin(B, t);
|
||||
if (NdbProfileRecord_start(B)
|
||||
|| NdbProfileRecord_received_at_pick(B, t)
|
||||
|| NdbProfileRecord_note_key_pick(B, t)
|
||||
|| NdbProfileRecord_profile_pick(B, t)
|
||||
|| NdbProfileRecord_lnurl_pick(B, t)) {
|
||||
return 0;
|
||||
}
|
||||
__flatbuffers_memoize_end(B, t, NdbProfileRecord_end(B));
|
||||
}
|
||||
|
||||
#include "flatcc/flatcc_epilogue.h"
|
||||
#endif /* PROFILE_BUILDER_H */
|
||||
412
nostrdb/src/bindings/c/profile_json_parser.h
Normal file
412
nostrdb/src/bindings/c/profile_json_parser.h
Normal file
@@ -0,0 +1,412 @@
|
||||
#ifndef PROFILE_JSON_PARSER_H
|
||||
#define PROFILE_JSON_PARSER_H
|
||||
|
||||
/* Generated by flatcc 0.6.1 FlatBuffers schema compiler for C by dvide.com */
|
||||
|
||||
#include "flatcc/flatcc_json_parser.h"
|
||||
#include "flatcc/flatcc_prologue.h"
|
||||
|
||||
/*
|
||||
* Parses the default root table or struct of the schema and constructs a FlatBuffer.
|
||||
*
|
||||
* Builder `B` must be initialized. `ctx` can be null but will hold
|
||||
* hold detailed error info on return when available.
|
||||
* Returns 0 on success, or error code.
|
||||
* `flags` : 0 by default, `flatcc_json_parser_f_skip_unknown` silently
|
||||
* ignores unknown table and structs fields, and union types.
|
||||
*/
|
||||
static int profile_parse_json(flatcc_builder_t *B, flatcc_json_parser_t *ctx,
|
||||
const char *buf, size_t bufsiz, int flags);
|
||||
|
||||
static const char *NdbProfile_parse_json_table(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result);
|
||||
static const char *NdbProfileRecord_parse_json_table(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result);
|
||||
static const char *profile_local_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end,
|
||||
int *value_type, uint64_t *value, int *aggregate);
|
||||
static const char *profile_global_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end,
|
||||
int *value_type, uint64_t *value, int *aggregate);
|
||||
|
||||
static const char *NdbProfile_parse_json_table(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result)
|
||||
{
|
||||
int more;
|
||||
void *pval;
|
||||
flatcc_builder_ref_t ref, *pref;
|
||||
const char *mark;
|
||||
uint64_t w;
|
||||
|
||||
*result = 0;
|
||||
if (flatcc_builder_start_table(ctx->ctx, 12)) goto failed;
|
||||
buf = flatcc_json_parser_object_start(ctx, buf, end, &more);
|
||||
while (more) {
|
||||
buf = flatcc_json_parser_symbol_start(ctx, buf, end);
|
||||
w = flatcc_json_parser_symbol_part(buf, end);
|
||||
if (w < 0x6c75643036000000) { /* branch "lud06" */
|
||||
if (w < 0x64616d75735f646f) { /* branch "damus_do" */
|
||||
if ((w & 0xffffffffffff0000) == 0x62616e6e65720000) { /* "banner" */
|
||||
buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 6);
|
||||
if (mark != buf) {
|
||||
buf = flatcc_json_parser_build_string(ctx, buf, end, &ref);
|
||||
if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 4))) goto failed;
|
||||
*pref = ref;
|
||||
} else {
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
}
|
||||
} else { /* "banner" */
|
||||
if ((w & 0xffffffffff000000) == 0x61626f7574000000) { /* "about" */
|
||||
buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 5);
|
||||
if (mark != buf) {
|
||||
buf = flatcc_json_parser_build_string(ctx, buf, end, &ref);
|
||||
if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 2))) goto failed;
|
||||
*pref = ref;
|
||||
} else {
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
}
|
||||
} else { /* "about" */
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
} /* "about" */
|
||||
} /* "banner" */
|
||||
} else { /* branch "damus_do" */
|
||||
if (w == 0x64616d75735f646f) { /* descend "damus_do" */
|
||||
buf += 8;
|
||||
w = flatcc_json_parser_symbol_part(buf, end);
|
||||
if (w == 0x6e6174696f6e5f76) { /* descend "nation_v" */
|
||||
buf += 8;
|
||||
w = flatcc_json_parser_symbol_part(buf, end);
|
||||
if ((w & 0xff00000000000000) == 0x3200000000000000) { /* "2" */
|
||||
buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 1);
|
||||
if (mark != buf) {
|
||||
int32_t val = 0;
|
||||
static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = {
|
||||
profile_local_json_parser_enum,
|
||||
profile_global_json_parser_enum, 0 };
|
||||
buf = flatcc_json_parser_int32(ctx, (mark = buf), end, &val);
|
||||
if (mark == buf) {
|
||||
buf = flatcc_json_parser_symbolic_int32(ctx, (mark = buf), end, symbolic_parsers, &val);
|
||||
if (buf == mark || buf == end) goto failed;
|
||||
}
|
||||
if (val != INT32_C(0) || (ctx->flags & flatcc_json_parser_f_force_add)) {
|
||||
if (!(pval = flatcc_builder_table_add(ctx->ctx, 10, 4, 4))) goto failed;
|
||||
flatbuffers_int32_write_to_pe(pval, val);
|
||||
}
|
||||
} else {
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
}
|
||||
} else { /* "2" */
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
} /* "2" */
|
||||
} else { /* descend "nation_v" */
|
||||
if ((w & 0xffffffffffff0000) == 0x6e6174696f6e0000) { /* "nation" */
|
||||
buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 6);
|
||||
if (mark != buf) {
|
||||
int32_t val = 0;
|
||||
static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = {
|
||||
profile_local_json_parser_enum,
|
||||
profile_global_json_parser_enum, 0 };
|
||||
buf = flatcc_json_parser_int32(ctx, (mark = buf), end, &val);
|
||||
if (mark == buf) {
|
||||
buf = flatcc_json_parser_symbolic_int32(ctx, (mark = buf), end, symbolic_parsers, &val);
|
||||
if (buf == mark || buf == end) goto failed;
|
||||
}
|
||||
if (val != INT32_C(0) || (ctx->flags & flatcc_json_parser_f_force_add)) {
|
||||
if (!(pval = flatcc_builder_table_add(ctx->ctx, 9, 4, 4))) goto failed;
|
||||
flatbuffers_int32_write_to_pe(pval, val);
|
||||
}
|
||||
} else {
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
}
|
||||
} else { /* "nation" */
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
} /* "nation" */
|
||||
} /* descend "nation_v" */
|
||||
} else { /* descend "damus_do" */
|
||||
if (w == 0x646973706c61795f) { /* descend "display_" */
|
||||
buf += 8;
|
||||
w = flatcc_json_parser_symbol_part(buf, end);
|
||||
if ((w & 0xffffffff00000000) == 0x6e616d6500000000) { /* "name" */
|
||||
buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 4);
|
||||
if (mark != buf) {
|
||||
buf = flatcc_json_parser_build_string(ctx, buf, end, &ref);
|
||||
if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 5))) goto failed;
|
||||
*pref = ref;
|
||||
} else {
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
}
|
||||
} else { /* "name" */
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
} /* "name" */
|
||||
} else { /* descend "display_" */
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
} /* descend "display_" */
|
||||
} /* descend "damus_do" */
|
||||
} /* branch "damus_do" */
|
||||
} else { /* branch "lud06" */
|
||||
if (w < 0x6e69703035000000) { /* branch "nip05" */
|
||||
if (w < 0x6c75643136000000) { /* branch "lud16" */
|
||||
if ((w & 0xffffffffff000000) == 0x6c75643036000000) { /* "lud06" */
|
||||
buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 5);
|
||||
if (mark != buf) {
|
||||
buf = flatcc_json_parser_build_string(ctx, buf, end, &ref);
|
||||
if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 11))) goto failed;
|
||||
*pref = ref;
|
||||
} else {
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
}
|
||||
} else { /* "lud06" */
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
} /* "lud06" */
|
||||
} else { /* branch "lud16" */
|
||||
if ((w & 0xffffffff00000000) == 0x6e616d6500000000) { /* "name" */
|
||||
buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 4);
|
||||
if (mark != buf) {
|
||||
buf = flatcc_json_parser_build_string(ctx, buf, end, &ref);
|
||||
if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 0))) goto failed;
|
||||
*pref = ref;
|
||||
} else {
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
}
|
||||
} else { /* "name" */
|
||||
if ((w & 0xffffffffff000000) == 0x6c75643136000000) { /* "lud16" */
|
||||
buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 5);
|
||||
if (mark != buf) {
|
||||
buf = flatcc_json_parser_build_string(ctx, buf, end, &ref);
|
||||
if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 3))) goto failed;
|
||||
*pref = ref;
|
||||
} else {
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
}
|
||||
} else { /* "lud16" */
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
} /* "lud16" */
|
||||
} /* "name" */
|
||||
} /* branch "lud16" */
|
||||
} else { /* branch "nip05" */
|
||||
if (w < 0x7069637475726500) { /* branch "picture" */
|
||||
if ((w & 0xffffffffff000000) == 0x6e69703035000000) { /* "nip05" */
|
||||
buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 5);
|
||||
if (mark != buf) {
|
||||
buf = flatcc_json_parser_build_string(ctx, buf, end, &ref);
|
||||
if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 8))) goto failed;
|
||||
*pref = ref;
|
||||
} else {
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
}
|
||||
} else { /* "nip05" */
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
} /* "nip05" */
|
||||
} else { /* branch "picture" */
|
||||
if (w < 0x7265616374696f6e) { /* branch "reaction" */
|
||||
if ((w & 0xffffffffffffff00) == 0x7069637475726500) { /* "picture" */
|
||||
buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 7);
|
||||
if (mark != buf) {
|
||||
buf = flatcc_json_parser_build_string(ctx, buf, end, &ref);
|
||||
if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 7))) goto failed;
|
||||
*pref = ref;
|
||||
} else {
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
}
|
||||
} else { /* "picture" */
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
} /* "picture" */
|
||||
} else { /* branch "reaction" */
|
||||
if (w == 0x7265616374696f6e) { /* descend "reaction" */
|
||||
buf += 8;
|
||||
w = flatcc_json_parser_symbol_part(buf, end);
|
||||
if ((w & 0xff00000000000000) == 0x7300000000000000) { /* "s" */
|
||||
buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 1);
|
||||
if (mark != buf) {
|
||||
uint8_t val = 0;
|
||||
static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = {
|
||||
profile_local_json_parser_enum,
|
||||
profile_global_json_parser_enum, 0 };
|
||||
buf = flatcc_json_parser_bool(ctx, (mark = buf), end, &val);
|
||||
if (mark == buf) {
|
||||
buf = flatcc_json_parser_symbolic_bool(ctx, (mark = buf), end, symbolic_parsers, &val);
|
||||
if (buf == mark || buf == end) goto failed;
|
||||
}
|
||||
if (val != UINT8_C(1) || (ctx->flags & flatcc_json_parser_f_force_add)) {
|
||||
if (!(pval = flatcc_builder_table_add(ctx->ctx, 6, 1, 1))) goto failed;
|
||||
flatbuffers_bool_write_to_pe(pval, val);
|
||||
}
|
||||
} else {
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
}
|
||||
} else { /* "s" */
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
} /* "s" */
|
||||
} else { /* descend "reaction" */
|
||||
if ((w & 0xffffffffffffff00) == 0x7765627369746500) { /* "website" */
|
||||
buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 7);
|
||||
if (mark != buf) {
|
||||
buf = flatcc_json_parser_build_string(ctx, buf, end, &ref);
|
||||
if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 1))) goto failed;
|
||||
*pref = ref;
|
||||
} else {
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
}
|
||||
} else { /* "website" */
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
} /* "website" */
|
||||
} /* descend "reaction" */
|
||||
} /* branch "reaction" */
|
||||
} /* branch "picture" */
|
||||
} /* branch "nip05" */
|
||||
} /* branch "lud06" */
|
||||
buf = flatcc_json_parser_object_end(ctx, buf, end, &more);
|
||||
}
|
||||
if (ctx->error) goto failed;
|
||||
if (!(*result = flatcc_builder_end_table(ctx->ctx))) goto failed;
|
||||
return buf;
|
||||
failed:
|
||||
return flatcc_json_parser_set_error(ctx, buf, end, flatcc_json_parser_error_runtime);
|
||||
}
|
||||
|
||||
static inline int NdbProfile_parse_json_as_root(flatcc_builder_t *B, flatcc_json_parser_t *ctx, const char *buf, size_t bufsiz, int flags, const char *fid)
|
||||
{
|
||||
return flatcc_json_parser_table_as_root(B, ctx, buf, bufsiz, flags, fid, NdbProfile_parse_json_table);
|
||||
}
|
||||
|
||||
static const char *NdbProfileRecord_parse_json_table(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result)
|
||||
{
|
||||
int more;
|
||||
void *pval;
|
||||
flatcc_builder_ref_t ref, *pref;
|
||||
const char *mark;
|
||||
uint64_t w;
|
||||
|
||||
*result = 0;
|
||||
if (flatcc_builder_start_table(ctx->ctx, 4)) goto failed;
|
||||
buf = flatcc_json_parser_object_start(ctx, buf, end, &more);
|
||||
while (more) {
|
||||
buf = flatcc_json_parser_symbol_start(ctx, buf, end);
|
||||
w = flatcc_json_parser_symbol_part(buf, end);
|
||||
if (w < 0x6e6f74655f6b6579) { /* branch "note_key" */
|
||||
if ((w & 0xffffffffff000000) == 0x6c6e75726c000000) { /* "lnurl" */
|
||||
buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 5);
|
||||
if (mark != buf) {
|
||||
buf = flatcc_json_parser_build_string(ctx, buf, end, &ref);
|
||||
if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 3))) goto failed;
|
||||
*pref = ref;
|
||||
} else {
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
}
|
||||
} else { /* "lnurl" */
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
} /* "lnurl" */
|
||||
} else { /* branch "note_key" */
|
||||
if (w < 0x70726f66696c6500) { /* branch "profile" */
|
||||
if (w == 0x6e6f74655f6b6579) { /* "note_key" */
|
||||
buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 8);
|
||||
if (mark != buf) {
|
||||
uint64_t val = 0;
|
||||
static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = {
|
||||
profile_local_json_parser_enum,
|
||||
profile_global_json_parser_enum, 0 };
|
||||
buf = flatcc_json_parser_uint64(ctx, (mark = buf), end, &val);
|
||||
if (mark == buf) {
|
||||
buf = flatcc_json_parser_symbolic_uint64(ctx, (mark = buf), end, symbolic_parsers, &val);
|
||||
if (buf == mark || buf == end) goto failed;
|
||||
}
|
||||
if (val != UINT64_C(0) || (ctx->flags & flatcc_json_parser_f_force_add)) {
|
||||
if (!(pval = flatcc_builder_table_add(ctx->ctx, 2, 8, 8))) goto failed;
|
||||
flatbuffers_uint64_write_to_pe(pval, val);
|
||||
}
|
||||
} else {
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
}
|
||||
} else { /* "note_key" */
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
} /* "note_key" */
|
||||
} else { /* branch "profile" */
|
||||
if ((w & 0xffffffffffffff00) == 0x70726f66696c6500) { /* "profile" */
|
||||
buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 7);
|
||||
if (mark != buf) {
|
||||
buf = NdbProfile_parse_json_table(ctx, buf, end, &ref);
|
||||
if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 0))) goto failed;
|
||||
*pref = ref;
|
||||
} else {
|
||||
goto pfguard1;
|
||||
}
|
||||
} else { /* "profile" */
|
||||
goto pfguard1;
|
||||
} /* "profile" */
|
||||
goto endpfguard1;
|
||||
pfguard1:
|
||||
if (w == 0x7265636569766564) { /* descend "received" */
|
||||
buf += 8;
|
||||
w = flatcc_json_parser_symbol_part(buf, end);
|
||||
if ((w & 0xffffff0000000000) == 0x5f61740000000000) { /* "_at" */
|
||||
buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 3);
|
||||
if (mark != buf) {
|
||||
uint64_t val = 0;
|
||||
static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = {
|
||||
profile_local_json_parser_enum,
|
||||
profile_global_json_parser_enum, 0 };
|
||||
buf = flatcc_json_parser_uint64(ctx, (mark = buf), end, &val);
|
||||
if (mark == buf) {
|
||||
buf = flatcc_json_parser_symbolic_uint64(ctx, (mark = buf), end, symbolic_parsers, &val);
|
||||
if (buf == mark || buf == end) goto failed;
|
||||
}
|
||||
if (val != UINT64_C(0) || (ctx->flags & flatcc_json_parser_f_force_add)) {
|
||||
if (!(pval = flatcc_builder_table_add(ctx->ctx, 1, 8, 8))) goto failed;
|
||||
flatbuffers_uint64_write_to_pe(pval, val);
|
||||
}
|
||||
} else {
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
}
|
||||
} else { /* "_at" */
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
} /* "_at" */
|
||||
} else { /* descend "received" */
|
||||
buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end);
|
||||
} /* descend "received" */
|
||||
endpfguard1:
|
||||
(void)0;
|
||||
} /* branch "profile" */
|
||||
} /* branch "note_key" */
|
||||
buf = flatcc_json_parser_object_end(ctx, buf, end, &more);
|
||||
}
|
||||
if (ctx->error) goto failed;
|
||||
if (!(*result = flatcc_builder_end_table(ctx->ctx))) goto failed;
|
||||
return buf;
|
||||
failed:
|
||||
return flatcc_json_parser_set_error(ctx, buf, end, flatcc_json_parser_error_runtime);
|
||||
}
|
||||
|
||||
static inline int NdbProfileRecord_parse_json_as_root(flatcc_builder_t *B, flatcc_json_parser_t *ctx, const char *buf, size_t bufsiz, int flags, const char *fid)
|
||||
{
|
||||
return flatcc_json_parser_table_as_root(B, ctx, buf, bufsiz, flags, fid, NdbProfileRecord_parse_json_table);
|
||||
}
|
||||
|
||||
static const char *profile_local_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end,
|
||||
int *value_type, uint64_t *value, int *aggregate)
|
||||
{
|
||||
/* Scope has no enum / union types to look up. */
|
||||
return buf; /* unmatched; */
|
||||
}
|
||||
|
||||
static const char *profile_global_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end,
|
||||
int *value_type, uint64_t *value, int *aggregate)
|
||||
{
|
||||
/* Global scope has no enum / union types to look up. */
|
||||
return buf; /* unmatched; */
|
||||
}
|
||||
|
||||
static int profile_parse_json(flatcc_builder_t *B, flatcc_json_parser_t *ctx,
|
||||
const char *buf, size_t bufsiz, int flags)
|
||||
{
|
||||
flatcc_json_parser_t parser;
|
||||
flatcc_builder_ref_t root;
|
||||
|
||||
ctx = ctx ? ctx : &parser;
|
||||
flatcc_json_parser_init(ctx, B, buf, buf + bufsiz, flags);
|
||||
if (flatcc_builder_start_buffer(B, 0, 0, 0)) return -1;
|
||||
NdbProfileRecord_parse_json_table(ctx, buf, buf + bufsiz, &root);
|
||||
if (ctx->error) {
|
||||
return ctx->error;
|
||||
}
|
||||
if (!flatcc_builder_end_buffer(B, root)) return -1;
|
||||
ctx->end_loc = buf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "flatcc/flatcc_epilogue.h"
|
||||
#endif /* PROFILE_JSON_PARSER_H */
|
||||
93
nostrdb/src/bindings/c/profile_reader.h
Normal file
93
nostrdb/src/bindings/c/profile_reader.h
Normal file
@@ -0,0 +1,93 @@
|
||||
#ifndef PROFILE_READER_H
|
||||
#define PROFILE_READER_H
|
||||
|
||||
/* Generated by flatcc 0.6.1 FlatBuffers schema compiler for C by dvide.com */
|
||||
|
||||
#ifndef FLATBUFFERS_COMMON_READER_H
|
||||
#include "flatbuffers_common_reader.h"
|
||||
#endif
|
||||
#include "flatcc/flatcc_flatbuffers.h"
|
||||
#ifndef __alignas_is_defined
|
||||
#include <stdalign.h>
|
||||
#endif
|
||||
#include "flatcc/flatcc_prologue.h"
|
||||
#ifndef flatbuffers_identifier
|
||||
#define flatbuffers_identifier 0
|
||||
#endif
|
||||
#ifndef flatbuffers_extension
|
||||
#define flatbuffers_extension "bin"
|
||||
#endif
|
||||
|
||||
|
||||
typedef const struct NdbProfile_table *NdbProfile_table_t;
|
||||
typedef struct NdbProfile_table *NdbProfile_mutable_table_t;
|
||||
typedef const flatbuffers_uoffset_t *NdbProfile_vec_t;
|
||||
typedef flatbuffers_uoffset_t *NdbProfile_mutable_vec_t;
|
||||
typedef const struct NdbProfileRecord_table *NdbProfileRecord_table_t;
|
||||
typedef struct NdbProfileRecord_table *NdbProfileRecord_mutable_table_t;
|
||||
typedef const flatbuffers_uoffset_t *NdbProfileRecord_vec_t;
|
||||
typedef flatbuffers_uoffset_t *NdbProfileRecord_mutable_vec_t;
|
||||
#ifndef NdbProfile_file_identifier
|
||||
#define NdbProfile_file_identifier 0
|
||||
#endif
|
||||
/* deprecated, use NdbProfile_file_identifier */
|
||||
#ifndef NdbProfile_identifier
|
||||
#define NdbProfile_identifier 0
|
||||
#endif
|
||||
#define NdbProfile_type_hash ((flatbuffers_thash_t)0xba639e28)
|
||||
#define NdbProfile_type_identifier "\x28\x9e\x63\xba"
|
||||
#ifndef NdbProfile_file_extension
|
||||
#define NdbProfile_file_extension "bin"
|
||||
#endif
|
||||
#ifndef NdbProfileRecord_file_identifier
|
||||
#define NdbProfileRecord_file_identifier 0
|
||||
#endif
|
||||
/* deprecated, use NdbProfileRecord_file_identifier */
|
||||
#ifndef NdbProfileRecord_identifier
|
||||
#define NdbProfileRecord_identifier 0
|
||||
#endif
|
||||
#define NdbProfileRecord_type_hash ((flatbuffers_thash_t)0xa1a8569d)
|
||||
#define NdbProfileRecord_type_identifier "\x9d\x56\xa8\xa1"
|
||||
#ifndef NdbProfileRecord_file_extension
|
||||
#define NdbProfileRecord_file_extension "bin"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
struct NdbProfile_table { uint8_t unused__; };
|
||||
|
||||
static inline size_t NdbProfile_vec_len(NdbProfile_vec_t vec)
|
||||
__flatbuffers_vec_len(vec)
|
||||
static inline NdbProfile_table_t NdbProfile_vec_at(NdbProfile_vec_t vec, size_t i)
|
||||
__flatbuffers_offset_vec_at(NdbProfile_table_t, vec, i, 0)
|
||||
__flatbuffers_table_as_root(NdbProfile)
|
||||
|
||||
__flatbuffers_define_string_field(0, NdbProfile, name, 0)
|
||||
__flatbuffers_define_string_field(1, NdbProfile, website, 0)
|
||||
__flatbuffers_define_string_field(2, NdbProfile, about, 0)
|
||||
__flatbuffers_define_string_field(3, NdbProfile, lud16, 0)
|
||||
__flatbuffers_define_string_field(4, NdbProfile, banner, 0)
|
||||
__flatbuffers_define_string_field(5, NdbProfile, display_name, 0)
|
||||
__flatbuffers_define_scalar_field(6, NdbProfile, reactions, flatbuffers_bool, flatbuffers_bool_t, UINT8_C(1))
|
||||
__flatbuffers_define_string_field(7, NdbProfile, picture, 0)
|
||||
__flatbuffers_define_string_field(8, NdbProfile, nip05, 0)
|
||||
__flatbuffers_define_scalar_field(9, NdbProfile, damus_donation, flatbuffers_int32, int32_t, INT32_C(0))
|
||||
__flatbuffers_define_scalar_field(10, NdbProfile, damus_donation_v2, flatbuffers_int32, int32_t, INT32_C(0))
|
||||
__flatbuffers_define_string_field(11, NdbProfile, lud06, 0)
|
||||
|
||||
struct NdbProfileRecord_table { uint8_t unused__; };
|
||||
|
||||
static inline size_t NdbProfileRecord_vec_len(NdbProfileRecord_vec_t vec)
|
||||
__flatbuffers_vec_len(vec)
|
||||
static inline NdbProfileRecord_table_t NdbProfileRecord_vec_at(NdbProfileRecord_vec_t vec, size_t i)
|
||||
__flatbuffers_offset_vec_at(NdbProfileRecord_table_t, vec, i, 0)
|
||||
__flatbuffers_table_as_root(NdbProfileRecord)
|
||||
|
||||
__flatbuffers_define_table_field(0, NdbProfileRecord, profile, NdbProfile_table_t, 0)
|
||||
__flatbuffers_define_scalar_field(1, NdbProfileRecord, received_at, flatbuffers_uint64, uint64_t, UINT64_C(0))
|
||||
__flatbuffers_define_scalar_field(2, NdbProfileRecord, note_key, flatbuffers_uint64, uint64_t, UINT64_C(0))
|
||||
__flatbuffers_define_string_field(3, NdbProfileRecord, lnurl, 0)
|
||||
|
||||
|
||||
#include "flatcc/flatcc_epilogue.h"
|
||||
#endif /* PROFILE_READER_H */
|
||||
84
nostrdb/src/bindings/c/profile_verifier.h
Normal file
84
nostrdb/src/bindings/c/profile_verifier.h
Normal file
@@ -0,0 +1,84 @@
|
||||
#ifndef PROFILE_VERIFIER_H
|
||||
#define PROFILE_VERIFIER_H
|
||||
|
||||
/* Generated by flatcc 0.6.1 FlatBuffers schema compiler for C by dvide.com */
|
||||
|
||||
#ifndef PROFILE_READER_H
|
||||
#include "profile_reader.h"
|
||||
#endif
|
||||
#include "flatcc/flatcc_verifier.h"
|
||||
#include "flatcc/flatcc_prologue.h"
|
||||
|
||||
static int NdbProfile_verify_table(flatcc_table_verifier_descriptor_t *td);
|
||||
static int NdbProfileRecord_verify_table(flatcc_table_verifier_descriptor_t *td);
|
||||
|
||||
static int NdbProfile_verify_table(flatcc_table_verifier_descriptor_t *td)
|
||||
{
|
||||
int ret;
|
||||
if ((ret = flatcc_verify_string_field(td, 0, 0) /* name */)) return ret;
|
||||
if ((ret = flatcc_verify_string_field(td, 1, 0) /* website */)) return ret;
|
||||
if ((ret = flatcc_verify_string_field(td, 2, 0) /* about */)) return ret;
|
||||
if ((ret = flatcc_verify_string_field(td, 3, 0) /* lud16 */)) return ret;
|
||||
if ((ret = flatcc_verify_string_field(td, 4, 0) /* banner */)) return ret;
|
||||
if ((ret = flatcc_verify_string_field(td, 5, 0) /* display_name */)) return ret;
|
||||
if ((ret = flatcc_verify_field(td, 6, 1, 1) /* reactions */)) return ret;
|
||||
if ((ret = flatcc_verify_string_field(td, 7, 0) /* picture */)) return ret;
|
||||
if ((ret = flatcc_verify_string_field(td, 8, 0) /* nip05 */)) return ret;
|
||||
if ((ret = flatcc_verify_field(td, 9, 4, 4) /* damus_donation */)) return ret;
|
||||
if ((ret = flatcc_verify_field(td, 10, 4, 4) /* damus_donation_v2 */)) return ret;
|
||||
if ((ret = flatcc_verify_string_field(td, 11, 0) /* lud06 */)) return ret;
|
||||
return flatcc_verify_ok;
|
||||
}
|
||||
|
||||
static inline int NdbProfile_verify_as_root(const void *buf, size_t bufsiz)
|
||||
{
|
||||
return flatcc_verify_table_as_root(buf, bufsiz, NdbProfile_identifier, &NdbProfile_verify_table);
|
||||
}
|
||||
|
||||
static inline int NdbProfile_verify_as_typed_root(const void *buf, size_t bufsiz)
|
||||
{
|
||||
return flatcc_verify_table_as_root(buf, bufsiz, NdbProfile_type_identifier, &NdbProfile_verify_table);
|
||||
}
|
||||
|
||||
static inline int NdbProfile_verify_as_root_with_identifier(const void *buf, size_t bufsiz, const char *fid)
|
||||
{
|
||||
return flatcc_verify_table_as_root(buf, bufsiz, fid, &NdbProfile_verify_table);
|
||||
}
|
||||
|
||||
static inline int NdbProfile_verify_as_root_with_type_hash(const void *buf, size_t bufsiz, flatbuffers_thash_t thash)
|
||||
{
|
||||
return flatcc_verify_table_as_typed_root(buf, bufsiz, thash, &NdbProfile_verify_table);
|
||||
}
|
||||
|
||||
static int NdbProfileRecord_verify_table(flatcc_table_verifier_descriptor_t *td)
|
||||
{
|
||||
int ret;
|
||||
if ((ret = flatcc_verify_table_field(td, 0, 0, &NdbProfile_verify_table) /* profile */)) return ret;
|
||||
if ((ret = flatcc_verify_field(td, 1, 8, 8) /* received_at */)) return ret;
|
||||
if ((ret = flatcc_verify_field(td, 2, 8, 8) /* note_key */)) return ret;
|
||||
if ((ret = flatcc_verify_string_field(td, 3, 0) /* lnurl */)) return ret;
|
||||
return flatcc_verify_ok;
|
||||
}
|
||||
|
||||
static inline int NdbProfileRecord_verify_as_root(const void *buf, size_t bufsiz)
|
||||
{
|
||||
return flatcc_verify_table_as_root(buf, bufsiz, NdbProfileRecord_identifier, &NdbProfileRecord_verify_table);
|
||||
}
|
||||
|
||||
static inline int NdbProfileRecord_verify_as_typed_root(const void *buf, size_t bufsiz)
|
||||
{
|
||||
return flatcc_verify_table_as_root(buf, bufsiz, NdbProfileRecord_type_identifier, &NdbProfileRecord_verify_table);
|
||||
}
|
||||
|
||||
static inline int NdbProfileRecord_verify_as_root_with_identifier(const void *buf, size_t bufsiz, const char *fid)
|
||||
{
|
||||
return flatcc_verify_table_as_root(buf, bufsiz, fid, &NdbProfileRecord_verify_table);
|
||||
}
|
||||
|
||||
static inline int NdbProfileRecord_verify_as_root_with_type_hash(const void *buf, size_t bufsiz, flatbuffers_thash_t thash)
|
||||
{
|
||||
return flatcc_verify_table_as_typed_root(buf, bufsiz, thash, &NdbProfileRecord_verify_table);
|
||||
}
|
||||
|
||||
#include "flatcc/flatcc_epilogue.h"
|
||||
#endif /* PROFILE_VERIFIER_H */
|
||||
0
nostrdb/src/bindings/rust/.dir
Normal file
0
nostrdb/src/bindings/rust/.dir
Normal file
264
nostrdb/src/bindings/rust/ndb_meta.rs
Normal file
264
nostrdb/src/bindings/rust/ndb_meta.rs
Normal file
@@ -0,0 +1,264 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
|
||||
// @generated
|
||||
|
||||
use core::mem;
|
||||
use core::cmp::Ordering;
|
||||
|
||||
extern crate flatbuffers;
|
||||
use self::flatbuffers::{EndianScalar, Follow};
|
||||
|
||||
pub enum NdbEventMetaOffset {}
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
|
||||
pub struct NdbEventMeta<'a> {
|
||||
pub _tab: flatbuffers::Table<'a>,
|
||||
}
|
||||
|
||||
impl<'a> flatbuffers::Follow<'a> for NdbEventMeta<'a> {
|
||||
type Inner = NdbEventMeta<'a>;
|
||||
#[inline]
|
||||
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
Self { _tab: flatbuffers::Table::new(buf, loc) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> NdbEventMeta<'a> {
|
||||
pub const VT_RECEIVED_AT: flatbuffers::VOffsetT = 4;
|
||||
pub const VT_REACTIONS: flatbuffers::VOffsetT = 6;
|
||||
pub const VT_QUOTES: flatbuffers::VOffsetT = 8;
|
||||
pub const VT_REPOSTS: flatbuffers::VOffsetT = 10;
|
||||
pub const VT_ZAPS: flatbuffers::VOffsetT = 12;
|
||||
pub const VT_ZAP_TOTAL: flatbuffers::VOffsetT = 14;
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
|
||||
NdbEventMeta { _tab: table }
|
||||
}
|
||||
#[allow(unused_mut)]
|
||||
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
|
||||
_fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>,
|
||||
args: &'args NdbEventMetaArgs
|
||||
) -> flatbuffers::WIPOffset<NdbEventMeta<'bldr>> {
|
||||
let mut builder = NdbEventMetaBuilder::new(_fbb);
|
||||
builder.add_zap_total(args.zap_total);
|
||||
builder.add_zaps(args.zaps);
|
||||
builder.add_reposts(args.reposts);
|
||||
builder.add_quotes(args.quotes);
|
||||
builder.add_reactions(args.reactions);
|
||||
builder.add_received_at(args.received_at);
|
||||
builder.finish()
|
||||
}
|
||||
|
||||
|
||||
#[inline]
|
||||
pub fn received_at(&self) -> i32 {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<i32>(NdbEventMeta::VT_RECEIVED_AT, Some(0)).unwrap()}
|
||||
}
|
||||
#[inline]
|
||||
pub fn reactions(&self) -> i32 {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<i32>(NdbEventMeta::VT_REACTIONS, Some(0)).unwrap()}
|
||||
}
|
||||
#[inline]
|
||||
pub fn quotes(&self) -> i32 {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<i32>(NdbEventMeta::VT_QUOTES, Some(0)).unwrap()}
|
||||
}
|
||||
#[inline]
|
||||
pub fn reposts(&self) -> i32 {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<i32>(NdbEventMeta::VT_REPOSTS, Some(0)).unwrap()}
|
||||
}
|
||||
#[inline]
|
||||
pub fn zaps(&self) -> i32 {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<i32>(NdbEventMeta::VT_ZAPS, Some(0)).unwrap()}
|
||||
}
|
||||
#[inline]
|
||||
pub fn zap_total(&self) -> i64 {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<i64>(NdbEventMeta::VT_ZAP_TOTAL, Some(0)).unwrap()}
|
||||
}
|
||||
}
|
||||
|
||||
impl flatbuffers::Verifiable for NdbEventMeta<'_> {
|
||||
#[inline]
|
||||
fn run_verifier(
|
||||
v: &mut flatbuffers::Verifier, pos: usize
|
||||
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
|
||||
use self::flatbuffers::Verifiable;
|
||||
v.visit_table(pos)?
|
||||
.visit_field::<i32>("received_at", Self::VT_RECEIVED_AT, false)?
|
||||
.visit_field::<i32>("reactions", Self::VT_REACTIONS, false)?
|
||||
.visit_field::<i32>("quotes", Self::VT_QUOTES, false)?
|
||||
.visit_field::<i32>("reposts", Self::VT_REPOSTS, false)?
|
||||
.visit_field::<i32>("zaps", Self::VT_ZAPS, false)?
|
||||
.visit_field::<i64>("zap_total", Self::VT_ZAP_TOTAL, false)?
|
||||
.finish();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
pub struct NdbEventMetaArgs {
|
||||
pub received_at: i32,
|
||||
pub reactions: i32,
|
||||
pub quotes: i32,
|
||||
pub reposts: i32,
|
||||
pub zaps: i32,
|
||||
pub zap_total: i64,
|
||||
}
|
||||
impl<'a> Default for NdbEventMetaArgs {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
NdbEventMetaArgs {
|
||||
received_at: 0,
|
||||
reactions: 0,
|
||||
quotes: 0,
|
||||
reposts: 0,
|
||||
zaps: 0,
|
||||
zap_total: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NdbEventMetaBuilder<'a: 'b, 'b> {
|
||||
fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a>,
|
||||
start_: flatbuffers::WIPOffset<flatbuffers::TableUnfinishedWIPOffset>,
|
||||
}
|
||||
impl<'a: 'b, 'b> NdbEventMetaBuilder<'a, 'b> {
|
||||
#[inline]
|
||||
pub fn add_received_at(&mut self, received_at: i32) {
|
||||
self.fbb_.push_slot::<i32>(NdbEventMeta::VT_RECEIVED_AT, received_at, 0);
|
||||
}
|
||||
#[inline]
|
||||
pub fn add_reactions(&mut self, reactions: i32) {
|
||||
self.fbb_.push_slot::<i32>(NdbEventMeta::VT_REACTIONS, reactions, 0);
|
||||
}
|
||||
#[inline]
|
||||
pub fn add_quotes(&mut self, quotes: i32) {
|
||||
self.fbb_.push_slot::<i32>(NdbEventMeta::VT_QUOTES, quotes, 0);
|
||||
}
|
||||
#[inline]
|
||||
pub fn add_reposts(&mut self, reposts: i32) {
|
||||
self.fbb_.push_slot::<i32>(NdbEventMeta::VT_REPOSTS, reposts, 0);
|
||||
}
|
||||
#[inline]
|
||||
pub fn add_zaps(&mut self, zaps: i32) {
|
||||
self.fbb_.push_slot::<i32>(NdbEventMeta::VT_ZAPS, zaps, 0);
|
||||
}
|
||||
#[inline]
|
||||
pub fn add_zap_total(&mut self, zap_total: i64) {
|
||||
self.fbb_.push_slot::<i64>(NdbEventMeta::VT_ZAP_TOTAL, zap_total, 0);
|
||||
}
|
||||
#[inline]
|
||||
pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>) -> NdbEventMetaBuilder<'a, 'b> {
|
||||
let start = _fbb.start_table();
|
||||
NdbEventMetaBuilder {
|
||||
fbb_: _fbb,
|
||||
start_: start,
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
pub fn finish(self) -> flatbuffers::WIPOffset<NdbEventMeta<'a>> {
|
||||
let o = self.fbb_.end_table(self.start_);
|
||||
flatbuffers::WIPOffset::new(o.value())
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for NdbEventMeta<'_> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
let mut ds = f.debug_struct("NdbEventMeta");
|
||||
ds.field("received_at", &self.received_at());
|
||||
ds.field("reactions", &self.reactions());
|
||||
ds.field("quotes", &self.quotes());
|
||||
ds.field("reposts", &self.reposts());
|
||||
ds.field("zaps", &self.zaps());
|
||||
ds.field("zap_total", &self.zap_total());
|
||||
ds.finish()
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
/// Verifies that a buffer of bytes contains a `NdbEventMeta`
|
||||
/// and returns it.
|
||||
/// Note that verification is still experimental and may not
|
||||
/// catch every error, or be maximally performant. For the
|
||||
/// previous, unchecked, behavior use
|
||||
/// `root_as_ndb_event_meta_unchecked`.
|
||||
pub fn root_as_ndb_event_meta(buf: &[u8]) -> Result<NdbEventMeta, flatbuffers::InvalidFlatbuffer> {
|
||||
flatbuffers::root::<NdbEventMeta>(buf)
|
||||
}
|
||||
#[inline]
|
||||
/// Verifies that a buffer of bytes contains a size prefixed
|
||||
/// `NdbEventMeta` and returns it.
|
||||
/// Note that verification is still experimental and may not
|
||||
/// catch every error, or be maximally performant. For the
|
||||
/// previous, unchecked, behavior use
|
||||
/// `size_prefixed_root_as_ndb_event_meta_unchecked`.
|
||||
pub fn size_prefixed_root_as_ndb_event_meta(buf: &[u8]) -> Result<NdbEventMeta, flatbuffers::InvalidFlatbuffer> {
|
||||
flatbuffers::size_prefixed_root::<NdbEventMeta>(buf)
|
||||
}
|
||||
#[inline]
|
||||
/// Verifies, with the given options, that a buffer of bytes
|
||||
/// contains a `NdbEventMeta` and returns it.
|
||||
/// Note that verification is still experimental and may not
|
||||
/// catch every error, or be maximally performant. For the
|
||||
/// previous, unchecked, behavior use
|
||||
/// `root_as_ndb_event_meta_unchecked`.
|
||||
pub fn root_as_ndb_event_meta_with_opts<'b, 'o>(
|
||||
opts: &'o flatbuffers::VerifierOptions,
|
||||
buf: &'b [u8],
|
||||
) -> Result<NdbEventMeta<'b>, flatbuffers::InvalidFlatbuffer> {
|
||||
flatbuffers::root_with_opts::<NdbEventMeta<'b>>(opts, buf)
|
||||
}
|
||||
#[inline]
|
||||
/// Verifies, with the given verifier options, that a buffer of
|
||||
/// bytes contains a size prefixed `NdbEventMeta` and returns
|
||||
/// it. Note that verification is still experimental and may not
|
||||
/// catch every error, or be maximally performant. For the
|
||||
/// previous, unchecked, behavior use
|
||||
/// `root_as_ndb_event_meta_unchecked`.
|
||||
pub fn size_prefixed_root_as_ndb_event_meta_with_opts<'b, 'o>(
|
||||
opts: &'o flatbuffers::VerifierOptions,
|
||||
buf: &'b [u8],
|
||||
) -> Result<NdbEventMeta<'b>, flatbuffers::InvalidFlatbuffer> {
|
||||
flatbuffers::size_prefixed_root_with_opts::<NdbEventMeta<'b>>(opts, buf)
|
||||
}
|
||||
#[inline]
|
||||
/// Assumes, without verification, that a buffer of bytes contains a NdbEventMeta and returns it.
|
||||
/// # Safety
|
||||
/// Callers must trust the given bytes do indeed contain a valid `NdbEventMeta`.
|
||||
pub unsafe fn root_as_ndb_event_meta_unchecked(buf: &[u8]) -> NdbEventMeta {
|
||||
flatbuffers::root_unchecked::<NdbEventMeta>(buf)
|
||||
}
|
||||
#[inline]
|
||||
/// Assumes, without verification, that a buffer of bytes contains a size prefixed NdbEventMeta and returns it.
|
||||
/// # Safety
|
||||
/// Callers must trust the given bytes do indeed contain a valid size prefixed `NdbEventMeta`.
|
||||
pub unsafe fn size_prefixed_root_as_ndb_event_meta_unchecked(buf: &[u8]) -> NdbEventMeta {
|
||||
flatbuffers::size_prefixed_root_unchecked::<NdbEventMeta>(buf)
|
||||
}
|
||||
#[inline]
|
||||
pub fn finish_ndb_event_meta_buffer<'a, 'b>(
|
||||
fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>,
|
||||
root: flatbuffers::WIPOffset<NdbEventMeta<'a>>) {
|
||||
fbb.finish(root, None);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn finish_size_prefixed_ndb_event_meta_buffer<'a, 'b>(fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>, root: flatbuffers::WIPOffset<NdbEventMeta<'a>>) {
|
||||
fbb.finish_size_prefixed(root, None);
|
||||
}
|
||||
514
nostrdb/src/bindings/rust/ndb_profile.rs
Normal file
514
nostrdb/src/bindings/rust/ndb_profile.rs
Normal file
@@ -0,0 +1,514 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
|
||||
// @generated
|
||||
|
||||
use core::mem;
|
||||
use core::cmp::Ordering;
|
||||
|
||||
extern crate flatbuffers;
|
||||
use self::flatbuffers::{EndianScalar, Follow};
|
||||
|
||||
pub enum NdbProfileOffset {}
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
|
||||
pub struct NdbProfile<'a> {
|
||||
pub _tab: flatbuffers::Table<'a>,
|
||||
}
|
||||
|
||||
impl<'a> flatbuffers::Follow<'a> for NdbProfile<'a> {
|
||||
type Inner = NdbProfile<'a>;
|
||||
#[inline]
|
||||
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
Self { _tab: flatbuffers::Table::new(buf, loc) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> NdbProfile<'a> {
|
||||
pub const VT_NAME: flatbuffers::VOffsetT = 4;
|
||||
pub const VT_WEBSITE: flatbuffers::VOffsetT = 6;
|
||||
pub const VT_ABOUT: flatbuffers::VOffsetT = 8;
|
||||
pub const VT_LUD16: flatbuffers::VOffsetT = 10;
|
||||
pub const VT_BANNER: flatbuffers::VOffsetT = 12;
|
||||
pub const VT_DISPLAY_NAME: flatbuffers::VOffsetT = 14;
|
||||
pub const VT_REACTIONS: flatbuffers::VOffsetT = 16;
|
||||
pub const VT_PICTURE: flatbuffers::VOffsetT = 18;
|
||||
pub const VT_NIP05: flatbuffers::VOffsetT = 20;
|
||||
pub const VT_DAMUS_DONATION: flatbuffers::VOffsetT = 22;
|
||||
pub const VT_DAMUS_DONATION_V2: flatbuffers::VOffsetT = 24;
|
||||
pub const VT_LUD06: flatbuffers::VOffsetT = 26;
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
|
||||
NdbProfile { _tab: table }
|
||||
}
|
||||
#[allow(unused_mut)]
|
||||
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
|
||||
_fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>,
|
||||
args: &'args NdbProfileArgs<'args>
|
||||
) -> flatbuffers::WIPOffset<NdbProfile<'bldr>> {
|
||||
let mut builder = NdbProfileBuilder::new(_fbb);
|
||||
if let Some(x) = args.lud06 { builder.add_lud06(x); }
|
||||
builder.add_damus_donation_v2(args.damus_donation_v2);
|
||||
builder.add_damus_donation(args.damus_donation);
|
||||
if let Some(x) = args.nip05 { builder.add_nip05(x); }
|
||||
if let Some(x) = args.picture { builder.add_picture(x); }
|
||||
if let Some(x) = args.display_name { builder.add_display_name(x); }
|
||||
if let Some(x) = args.banner { builder.add_banner(x); }
|
||||
if let Some(x) = args.lud16 { builder.add_lud16(x); }
|
||||
if let Some(x) = args.about { builder.add_about(x); }
|
||||
if let Some(x) = args.website { builder.add_website(x); }
|
||||
if let Some(x) = args.name { builder.add_name(x); }
|
||||
builder.add_reactions(args.reactions);
|
||||
builder.finish()
|
||||
}
|
||||
|
||||
|
||||
#[inline]
|
||||
pub fn name(&self) -> Option<&'a str> {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(NdbProfile::VT_NAME, None)}
|
||||
}
|
||||
#[inline]
|
||||
pub fn website(&self) -> Option<&'a str> {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(NdbProfile::VT_WEBSITE, None)}
|
||||
}
|
||||
#[inline]
|
||||
pub fn about(&self) -> Option<&'a str> {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(NdbProfile::VT_ABOUT, None)}
|
||||
}
|
||||
#[inline]
|
||||
pub fn lud16(&self) -> Option<&'a str> {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(NdbProfile::VT_LUD16, None)}
|
||||
}
|
||||
#[inline]
|
||||
pub fn banner(&self) -> Option<&'a str> {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(NdbProfile::VT_BANNER, None)}
|
||||
}
|
||||
#[inline]
|
||||
pub fn display_name(&self) -> Option<&'a str> {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(NdbProfile::VT_DISPLAY_NAME, None)}
|
||||
}
|
||||
#[inline]
|
||||
pub fn reactions(&self) -> bool {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<bool>(NdbProfile::VT_REACTIONS, Some(true)).unwrap()}
|
||||
}
|
||||
#[inline]
|
||||
pub fn picture(&self) -> Option<&'a str> {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(NdbProfile::VT_PICTURE, None)}
|
||||
}
|
||||
#[inline]
|
||||
pub fn nip05(&self) -> Option<&'a str> {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(NdbProfile::VT_NIP05, None)}
|
||||
}
|
||||
#[inline]
|
||||
pub fn damus_donation(&self) -> i32 {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<i32>(NdbProfile::VT_DAMUS_DONATION, Some(0)).unwrap()}
|
||||
}
|
||||
#[inline]
|
||||
pub fn damus_donation_v2(&self) -> i32 {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<i32>(NdbProfile::VT_DAMUS_DONATION_V2, Some(0)).unwrap()}
|
||||
}
|
||||
#[inline]
|
||||
pub fn lud06(&self) -> Option<&'a str> {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(NdbProfile::VT_LUD06, None)}
|
||||
}
|
||||
}
|
||||
|
||||
impl flatbuffers::Verifiable for NdbProfile<'_> {
|
||||
#[inline]
|
||||
fn run_verifier(
|
||||
v: &mut flatbuffers::Verifier, pos: usize
|
||||
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
|
||||
use self::flatbuffers::Verifiable;
|
||||
v.visit_table(pos)?
|
||||
.visit_field::<flatbuffers::ForwardsUOffset<&str>>("name", Self::VT_NAME, false)?
|
||||
.visit_field::<flatbuffers::ForwardsUOffset<&str>>("website", Self::VT_WEBSITE, false)?
|
||||
.visit_field::<flatbuffers::ForwardsUOffset<&str>>("about", Self::VT_ABOUT, false)?
|
||||
.visit_field::<flatbuffers::ForwardsUOffset<&str>>("lud16", Self::VT_LUD16, false)?
|
||||
.visit_field::<flatbuffers::ForwardsUOffset<&str>>("banner", Self::VT_BANNER, false)?
|
||||
.visit_field::<flatbuffers::ForwardsUOffset<&str>>("display_name", Self::VT_DISPLAY_NAME, false)?
|
||||
.visit_field::<bool>("reactions", Self::VT_REACTIONS, false)?
|
||||
.visit_field::<flatbuffers::ForwardsUOffset<&str>>("picture", Self::VT_PICTURE, false)?
|
||||
.visit_field::<flatbuffers::ForwardsUOffset<&str>>("nip05", Self::VT_NIP05, false)?
|
||||
.visit_field::<i32>("damus_donation", Self::VT_DAMUS_DONATION, false)?
|
||||
.visit_field::<i32>("damus_donation_v2", Self::VT_DAMUS_DONATION_V2, false)?
|
||||
.visit_field::<flatbuffers::ForwardsUOffset<&str>>("lud06", Self::VT_LUD06, false)?
|
||||
.finish();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
pub struct NdbProfileArgs<'a> {
|
||||
pub name: Option<flatbuffers::WIPOffset<&'a str>>,
|
||||
pub website: Option<flatbuffers::WIPOffset<&'a str>>,
|
||||
pub about: Option<flatbuffers::WIPOffset<&'a str>>,
|
||||
pub lud16: Option<flatbuffers::WIPOffset<&'a str>>,
|
||||
pub banner: Option<flatbuffers::WIPOffset<&'a str>>,
|
||||
pub display_name: Option<flatbuffers::WIPOffset<&'a str>>,
|
||||
pub reactions: bool,
|
||||
pub picture: Option<flatbuffers::WIPOffset<&'a str>>,
|
||||
pub nip05: Option<flatbuffers::WIPOffset<&'a str>>,
|
||||
pub damus_donation: i32,
|
||||
pub damus_donation_v2: i32,
|
||||
pub lud06: Option<flatbuffers::WIPOffset<&'a str>>,
|
||||
}
|
||||
impl<'a> Default for NdbProfileArgs<'a> {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
NdbProfileArgs {
|
||||
name: None,
|
||||
website: None,
|
||||
about: None,
|
||||
lud16: None,
|
||||
banner: None,
|
||||
display_name: None,
|
||||
reactions: true,
|
||||
picture: None,
|
||||
nip05: None,
|
||||
damus_donation: 0,
|
||||
damus_donation_v2: 0,
|
||||
lud06: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NdbProfileBuilder<'a: 'b, 'b> {
|
||||
fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a>,
|
||||
start_: flatbuffers::WIPOffset<flatbuffers::TableUnfinishedWIPOffset>,
|
||||
}
|
||||
impl<'a: 'b, 'b> NdbProfileBuilder<'a, 'b> {
|
||||
#[inline]
|
||||
pub fn add_name(&mut self, name: flatbuffers::WIPOffset<&'b str>) {
|
||||
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>(NdbProfile::VT_NAME, name);
|
||||
}
|
||||
#[inline]
|
||||
pub fn add_website(&mut self, website: flatbuffers::WIPOffset<&'b str>) {
|
||||
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>(NdbProfile::VT_WEBSITE, website);
|
||||
}
|
||||
#[inline]
|
||||
pub fn add_about(&mut self, about: flatbuffers::WIPOffset<&'b str>) {
|
||||
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>(NdbProfile::VT_ABOUT, about);
|
||||
}
|
||||
#[inline]
|
||||
pub fn add_lud16(&mut self, lud16: flatbuffers::WIPOffset<&'b str>) {
|
||||
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>(NdbProfile::VT_LUD16, lud16);
|
||||
}
|
||||
#[inline]
|
||||
pub fn add_banner(&mut self, banner: flatbuffers::WIPOffset<&'b str>) {
|
||||
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>(NdbProfile::VT_BANNER, banner);
|
||||
}
|
||||
#[inline]
|
||||
pub fn add_display_name(&mut self, display_name: flatbuffers::WIPOffset<&'b str>) {
|
||||
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>(NdbProfile::VT_DISPLAY_NAME, display_name);
|
||||
}
|
||||
#[inline]
|
||||
pub fn add_reactions(&mut self, reactions: bool) {
|
||||
self.fbb_.push_slot::<bool>(NdbProfile::VT_REACTIONS, reactions, true);
|
||||
}
|
||||
#[inline]
|
||||
pub fn add_picture(&mut self, picture: flatbuffers::WIPOffset<&'b str>) {
|
||||
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>(NdbProfile::VT_PICTURE, picture);
|
||||
}
|
||||
#[inline]
|
||||
pub fn add_nip05(&mut self, nip05: flatbuffers::WIPOffset<&'b str>) {
|
||||
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>(NdbProfile::VT_NIP05, nip05);
|
||||
}
|
||||
#[inline]
|
||||
pub fn add_damus_donation(&mut self, damus_donation: i32) {
|
||||
self.fbb_.push_slot::<i32>(NdbProfile::VT_DAMUS_DONATION, damus_donation, 0);
|
||||
}
|
||||
#[inline]
|
||||
pub fn add_damus_donation_v2(&mut self, damus_donation_v2: i32) {
|
||||
self.fbb_.push_slot::<i32>(NdbProfile::VT_DAMUS_DONATION_V2, damus_donation_v2, 0);
|
||||
}
|
||||
#[inline]
|
||||
pub fn add_lud06(&mut self, lud06: flatbuffers::WIPOffset<&'b str>) {
|
||||
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>(NdbProfile::VT_LUD06, lud06);
|
||||
}
|
||||
#[inline]
|
||||
pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>) -> NdbProfileBuilder<'a, 'b> {
|
||||
let start = _fbb.start_table();
|
||||
NdbProfileBuilder {
|
||||
fbb_: _fbb,
|
||||
start_: start,
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
pub fn finish(self) -> flatbuffers::WIPOffset<NdbProfile<'a>> {
|
||||
let o = self.fbb_.end_table(self.start_);
|
||||
flatbuffers::WIPOffset::new(o.value())
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for NdbProfile<'_> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
let mut ds = f.debug_struct("NdbProfile");
|
||||
ds.field("name", &self.name());
|
||||
ds.field("website", &self.website());
|
||||
ds.field("about", &self.about());
|
||||
ds.field("lud16", &self.lud16());
|
||||
ds.field("banner", &self.banner());
|
||||
ds.field("display_name", &self.display_name());
|
||||
ds.field("reactions", &self.reactions());
|
||||
ds.field("picture", &self.picture());
|
||||
ds.field("nip05", &self.nip05());
|
||||
ds.field("damus_donation", &self.damus_donation());
|
||||
ds.field("damus_donation_v2", &self.damus_donation_v2());
|
||||
ds.field("lud06", &self.lud06());
|
||||
ds.finish()
|
||||
}
|
||||
}
|
||||
pub enum NdbProfileRecordOffset {}
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
|
||||
pub struct NdbProfileRecord<'a> {
|
||||
pub _tab: flatbuffers::Table<'a>,
|
||||
}
|
||||
|
||||
impl<'a> flatbuffers::Follow<'a> for NdbProfileRecord<'a> {
|
||||
type Inner = NdbProfileRecord<'a>;
|
||||
#[inline]
|
||||
unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
|
||||
Self { _tab: flatbuffers::Table::new(buf, loc) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> NdbProfileRecord<'a> {
|
||||
pub const VT_PROFILE: flatbuffers::VOffsetT = 4;
|
||||
pub const VT_RECEIVED_AT: flatbuffers::VOffsetT = 6;
|
||||
pub const VT_NOTE_KEY: flatbuffers::VOffsetT = 8;
|
||||
pub const VT_LNURL: flatbuffers::VOffsetT = 10;
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
|
||||
NdbProfileRecord { _tab: table }
|
||||
}
|
||||
#[allow(unused_mut)]
|
||||
pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
|
||||
_fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>,
|
||||
args: &'args NdbProfileRecordArgs<'args>
|
||||
) -> flatbuffers::WIPOffset<NdbProfileRecord<'bldr>> {
|
||||
let mut builder = NdbProfileRecordBuilder::new(_fbb);
|
||||
builder.add_note_key(args.note_key);
|
||||
builder.add_received_at(args.received_at);
|
||||
if let Some(x) = args.lnurl { builder.add_lnurl(x); }
|
||||
if let Some(x) = args.profile { builder.add_profile(x); }
|
||||
builder.finish()
|
||||
}
|
||||
|
||||
|
||||
#[inline]
|
||||
pub fn profile(&self) -> Option<NdbProfile<'a>> {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<NdbProfile>>(NdbProfileRecord::VT_PROFILE, None)}
|
||||
}
|
||||
#[inline]
|
||||
pub fn received_at(&self) -> u64 {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<u64>(NdbProfileRecord::VT_RECEIVED_AT, Some(0)).unwrap()}
|
||||
}
|
||||
#[inline]
|
||||
pub fn note_key(&self) -> u64 {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<u64>(NdbProfileRecord::VT_NOTE_KEY, Some(0)).unwrap()}
|
||||
}
|
||||
#[inline]
|
||||
pub fn lnurl(&self) -> Option<&'a str> {
|
||||
// Safety:
|
||||
// Created from valid Table for this object
|
||||
// which contains a valid value in this slot
|
||||
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(NdbProfileRecord::VT_LNURL, None)}
|
||||
}
|
||||
}
|
||||
|
||||
impl flatbuffers::Verifiable for NdbProfileRecord<'_> {
|
||||
#[inline]
|
||||
fn run_verifier(
|
||||
v: &mut flatbuffers::Verifier, pos: usize
|
||||
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
|
||||
use self::flatbuffers::Verifiable;
|
||||
v.visit_table(pos)?
|
||||
.visit_field::<flatbuffers::ForwardsUOffset<NdbProfile>>("profile", Self::VT_PROFILE, false)?
|
||||
.visit_field::<u64>("received_at", Self::VT_RECEIVED_AT, false)?
|
||||
.visit_field::<u64>("note_key", Self::VT_NOTE_KEY, false)?
|
||||
.visit_field::<flatbuffers::ForwardsUOffset<&str>>("lnurl", Self::VT_LNURL, false)?
|
||||
.finish();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
pub struct NdbProfileRecordArgs<'a> {
|
||||
pub profile: Option<flatbuffers::WIPOffset<NdbProfile<'a>>>,
|
||||
pub received_at: u64,
|
||||
pub note_key: u64,
|
||||
pub lnurl: Option<flatbuffers::WIPOffset<&'a str>>,
|
||||
}
|
||||
impl<'a> Default for NdbProfileRecordArgs<'a> {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
NdbProfileRecordArgs {
|
||||
profile: None,
|
||||
received_at: 0,
|
||||
note_key: 0,
|
||||
lnurl: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NdbProfileRecordBuilder<'a: 'b, 'b> {
|
||||
fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a>,
|
||||
start_: flatbuffers::WIPOffset<flatbuffers::TableUnfinishedWIPOffset>,
|
||||
}
|
||||
impl<'a: 'b, 'b> NdbProfileRecordBuilder<'a, 'b> {
|
||||
#[inline]
|
||||
pub fn add_profile(&mut self, profile: flatbuffers::WIPOffset<NdbProfile<'b >>) {
|
||||
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<NdbProfile>>(NdbProfileRecord::VT_PROFILE, profile);
|
||||
}
|
||||
#[inline]
|
||||
pub fn add_received_at(&mut self, received_at: u64) {
|
||||
self.fbb_.push_slot::<u64>(NdbProfileRecord::VT_RECEIVED_AT, received_at, 0);
|
||||
}
|
||||
#[inline]
|
||||
pub fn add_note_key(&mut self, note_key: u64) {
|
||||
self.fbb_.push_slot::<u64>(NdbProfileRecord::VT_NOTE_KEY, note_key, 0);
|
||||
}
|
||||
#[inline]
|
||||
pub fn add_lnurl(&mut self, lnurl: flatbuffers::WIPOffset<&'b str>) {
|
||||
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>(NdbProfileRecord::VT_LNURL, lnurl);
|
||||
}
|
||||
#[inline]
|
||||
pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>) -> NdbProfileRecordBuilder<'a, 'b> {
|
||||
let start = _fbb.start_table();
|
||||
NdbProfileRecordBuilder {
|
||||
fbb_: _fbb,
|
||||
start_: start,
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
pub fn finish(self) -> flatbuffers::WIPOffset<NdbProfileRecord<'a>> {
|
||||
let o = self.fbb_.end_table(self.start_);
|
||||
flatbuffers::WIPOffset::new(o.value())
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for NdbProfileRecord<'_> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
let mut ds = f.debug_struct("NdbProfileRecord");
|
||||
ds.field("profile", &self.profile());
|
||||
ds.field("received_at", &self.received_at());
|
||||
ds.field("note_key", &self.note_key());
|
||||
ds.field("lnurl", &self.lnurl());
|
||||
ds.finish()
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
/// Verifies that a buffer of bytes contains a `NdbProfileRecord`
|
||||
/// and returns it.
|
||||
/// Note that verification is still experimental and may not
|
||||
/// catch every error, or be maximally performant. For the
|
||||
/// previous, unchecked, behavior use
|
||||
/// `root_as_ndb_profile_record_unchecked`.
|
||||
pub fn root_as_ndb_profile_record(buf: &[u8]) -> Result<NdbProfileRecord, flatbuffers::InvalidFlatbuffer> {
|
||||
flatbuffers::root::<NdbProfileRecord>(buf)
|
||||
}
|
||||
#[inline]
|
||||
/// Verifies that a buffer of bytes contains a size prefixed
|
||||
/// `NdbProfileRecord` and returns it.
|
||||
/// Note that verification is still experimental and may not
|
||||
/// catch every error, or be maximally performant. For the
|
||||
/// previous, unchecked, behavior use
|
||||
/// `size_prefixed_root_as_ndb_profile_record_unchecked`.
|
||||
pub fn size_prefixed_root_as_ndb_profile_record(buf: &[u8]) -> Result<NdbProfileRecord, flatbuffers::InvalidFlatbuffer> {
|
||||
flatbuffers::size_prefixed_root::<NdbProfileRecord>(buf)
|
||||
}
|
||||
#[inline]
|
||||
/// Verifies, with the given options, that a buffer of bytes
|
||||
/// contains a `NdbProfileRecord` and returns it.
|
||||
/// Note that verification is still experimental and may not
|
||||
/// catch every error, or be maximally performant. For the
|
||||
/// previous, unchecked, behavior use
|
||||
/// `root_as_ndb_profile_record_unchecked`.
|
||||
pub fn root_as_ndb_profile_record_with_opts<'b, 'o>(
|
||||
opts: &'o flatbuffers::VerifierOptions,
|
||||
buf: &'b [u8],
|
||||
) -> Result<NdbProfileRecord<'b>, flatbuffers::InvalidFlatbuffer> {
|
||||
flatbuffers::root_with_opts::<NdbProfileRecord<'b>>(opts, buf)
|
||||
}
|
||||
#[inline]
|
||||
/// Verifies, with the given verifier options, that a buffer of
|
||||
/// bytes contains a size prefixed `NdbProfileRecord` and returns
|
||||
/// it. Note that verification is still experimental and may not
|
||||
/// catch every error, or be maximally performant. For the
|
||||
/// previous, unchecked, behavior use
|
||||
/// `root_as_ndb_profile_record_unchecked`.
|
||||
pub fn size_prefixed_root_as_ndb_profile_record_with_opts<'b, 'o>(
|
||||
opts: &'o flatbuffers::VerifierOptions,
|
||||
buf: &'b [u8],
|
||||
) -> Result<NdbProfileRecord<'b>, flatbuffers::InvalidFlatbuffer> {
|
||||
flatbuffers::size_prefixed_root_with_opts::<NdbProfileRecord<'b>>(opts, buf)
|
||||
}
|
||||
#[inline]
|
||||
/// Assumes, without verification, that a buffer of bytes contains a NdbProfileRecord and returns it.
|
||||
/// # Safety
|
||||
/// Callers must trust the given bytes do indeed contain a valid `NdbProfileRecord`.
|
||||
pub unsafe fn root_as_ndb_profile_record_unchecked(buf: &[u8]) -> NdbProfileRecord {
|
||||
flatbuffers::root_unchecked::<NdbProfileRecord>(buf)
|
||||
}
|
||||
#[inline]
|
||||
/// Assumes, without verification, that a buffer of bytes contains a size prefixed NdbProfileRecord and returns it.
|
||||
/// # Safety
|
||||
/// Callers must trust the given bytes do indeed contain a valid size prefixed `NdbProfileRecord`.
|
||||
pub unsafe fn size_prefixed_root_as_ndb_profile_record_unchecked(buf: &[u8]) -> NdbProfileRecord {
|
||||
flatbuffers::size_prefixed_root_unchecked::<NdbProfileRecord>(buf)
|
||||
}
|
||||
#[inline]
|
||||
pub fn finish_ndb_profile_record_buffer<'a, 'b>(
|
||||
fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>,
|
||||
root: flatbuffers::WIPOffset<NdbProfileRecord<'a>>) {
|
||||
fbb.finish(root, None);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn finish_size_prefixed_ndb_profile_record_buffer<'a, 'b>(fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>, root: flatbuffers::WIPOffset<NdbProfileRecord<'a>>) {
|
||||
fbb.finish_size_prefixed(root, None);
|
||||
}
|
||||
71
nostrdb/src/bindings/swift/NdbMeta.swift
Normal file
71
nostrdb/src/bindings/swift/NdbMeta.swift
Normal file
@@ -0,0 +1,71 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// swiftlint:disable all
|
||||
// swiftformat:disable all
|
||||
|
||||
import FlatBuffers
|
||||
|
||||
public struct NdbEventMeta: FlatBufferObject, Verifiable {
|
||||
|
||||
static func validateVersion() { FlatBuffersVersion_23_5_26() }
|
||||
public var __buffer: ByteBuffer! { return _accessor.bb }
|
||||
private var _accessor: Table
|
||||
|
||||
private init(_ t: Table) { _accessor = t }
|
||||
public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) }
|
||||
|
||||
private enum VTOFFSET: VOffset {
|
||||
case receivedAt = 4
|
||||
case reactions = 6
|
||||
case quotes = 8
|
||||
case reposts = 10
|
||||
case zaps = 12
|
||||
case zapTotal = 14
|
||||
var v: Int32 { Int32(self.rawValue) }
|
||||
var p: VOffset { self.rawValue }
|
||||
}
|
||||
|
||||
public var receivedAt: Int32 { let o = _accessor.offset(VTOFFSET.receivedAt.v); return o == 0 ? 0 : _accessor.readBuffer(of: Int32.self, at: o) }
|
||||
public var reactions: Int32 { let o = _accessor.offset(VTOFFSET.reactions.v); return o == 0 ? 0 : _accessor.readBuffer(of: Int32.self, at: o) }
|
||||
public var quotes: Int32 { let o = _accessor.offset(VTOFFSET.quotes.v); return o == 0 ? 0 : _accessor.readBuffer(of: Int32.self, at: o) }
|
||||
public var reposts: Int32 { let o = _accessor.offset(VTOFFSET.reposts.v); return o == 0 ? 0 : _accessor.readBuffer(of: Int32.self, at: o) }
|
||||
public var zaps: Int32 { let o = _accessor.offset(VTOFFSET.zaps.v); return o == 0 ? 0 : _accessor.readBuffer(of: Int32.self, at: o) }
|
||||
public var zapTotal: Int64 { let o = _accessor.offset(VTOFFSET.zapTotal.v); return o == 0 ? 0 : _accessor.readBuffer(of: Int64.self, at: o) }
|
||||
public static func startNdbEventMeta(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 6) }
|
||||
public static func add(receivedAt: Int32, _ fbb: inout FlatBufferBuilder) { fbb.add(element: receivedAt, def: 0, at: VTOFFSET.receivedAt.p) }
|
||||
public static func add(reactions: Int32, _ fbb: inout FlatBufferBuilder) { fbb.add(element: reactions, def: 0, at: VTOFFSET.reactions.p) }
|
||||
public static func add(quotes: Int32, _ fbb: inout FlatBufferBuilder) { fbb.add(element: quotes, def: 0, at: VTOFFSET.quotes.p) }
|
||||
public static func add(reposts: Int32, _ fbb: inout FlatBufferBuilder) { fbb.add(element: reposts, def: 0, at: VTOFFSET.reposts.p) }
|
||||
public static func add(zaps: Int32, _ fbb: inout FlatBufferBuilder) { fbb.add(element: zaps, def: 0, at: VTOFFSET.zaps.p) }
|
||||
public static func add(zapTotal: Int64, _ fbb: inout FlatBufferBuilder) { fbb.add(element: zapTotal, def: 0, at: VTOFFSET.zapTotal.p) }
|
||||
public static func endNdbEventMeta(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end }
|
||||
public static func createNdbEventMeta(
|
||||
_ fbb: inout FlatBufferBuilder,
|
||||
receivedAt: Int32 = 0,
|
||||
reactions: Int32 = 0,
|
||||
quotes: Int32 = 0,
|
||||
reposts: Int32 = 0,
|
||||
zaps: Int32 = 0,
|
||||
zapTotal: Int64 = 0
|
||||
) -> Offset {
|
||||
let __start = NdbEventMeta.startNdbEventMeta(&fbb)
|
||||
NdbEventMeta.add(receivedAt: receivedAt, &fbb)
|
||||
NdbEventMeta.add(reactions: reactions, &fbb)
|
||||
NdbEventMeta.add(quotes: quotes, &fbb)
|
||||
NdbEventMeta.add(reposts: reposts, &fbb)
|
||||
NdbEventMeta.add(zaps: zaps, &fbb)
|
||||
NdbEventMeta.add(zapTotal: zapTotal, &fbb)
|
||||
return NdbEventMeta.endNdbEventMeta(&fbb, start: __start)
|
||||
}
|
||||
|
||||
public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable {
|
||||
var _v = try verifier.visitTable(at: position)
|
||||
try _v.visit(field: VTOFFSET.receivedAt.p, fieldName: "receivedAt", required: false, type: Int32.self)
|
||||
try _v.visit(field: VTOFFSET.reactions.p, fieldName: "reactions", required: false, type: Int32.self)
|
||||
try _v.visit(field: VTOFFSET.quotes.p, fieldName: "quotes", required: false, type: Int32.self)
|
||||
try _v.visit(field: VTOFFSET.reposts.p, fieldName: "reposts", required: false, type: Int32.self)
|
||||
try _v.visit(field: VTOFFSET.zaps.p, fieldName: "zaps", required: false, type: Int32.self)
|
||||
try _v.visit(field: VTOFFSET.zapTotal.p, fieldName: "zapTotal", required: false, type: Int64.self)
|
||||
_v.finish()
|
||||
}
|
||||
}
|
||||
|
||||
231
nostrdb/src/bindings/swift/NdbProfile.swift
Normal file
231
nostrdb/src/bindings/swift/NdbProfile.swift
Normal file
@@ -0,0 +1,231 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// swiftlint:disable all
|
||||
// swiftformat:disable all
|
||||
|
||||
import FlatBuffers
|
||||
|
||||
public struct NdbProfile: FlatBufferObject, Verifiable {
|
||||
|
||||
static func validateVersion() { FlatBuffersVersion_23_5_26() }
|
||||
public var __buffer: ByteBuffer! { return _accessor.bb }
|
||||
private var _accessor: Table
|
||||
|
||||
private init(_ t: Table) { _accessor = t }
|
||||
public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) }
|
||||
|
||||
private enum VTOFFSET: VOffset {
|
||||
case name = 4
|
||||
case website = 6
|
||||
case about = 8
|
||||
case lud16 = 10
|
||||
case banner = 12
|
||||
case displayName = 14
|
||||
case reactions = 16
|
||||
case picture = 18
|
||||
case nip05 = 20
|
||||
case damusDonation = 22
|
||||
case damusDonationV2 = 24
|
||||
case lud06 = 26
|
||||
var v: Int32 { Int32(self.rawValue) }
|
||||
var p: VOffset { self.rawValue }
|
||||
}
|
||||
|
||||
public var name: String? { let o = _accessor.offset(VTOFFSET.name.v); return o == 0 ? nil : _accessor.string(at: o) }
|
||||
public var nameSegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.name.v) }
|
||||
public var website: String? { let o = _accessor.offset(VTOFFSET.website.v); return o == 0 ? nil : _accessor.string(at: o) }
|
||||
public var websiteSegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.website.v) }
|
||||
public var about: String? { let o = _accessor.offset(VTOFFSET.about.v); return o == 0 ? nil : _accessor.string(at: o) }
|
||||
public var aboutSegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.about.v) }
|
||||
public var lud16: String? { let o = _accessor.offset(VTOFFSET.lud16.v); return o == 0 ? nil : _accessor.string(at: o) }
|
||||
public var lud16SegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.lud16.v) }
|
||||
public var banner: String? { let o = _accessor.offset(VTOFFSET.banner.v); return o == 0 ? nil : _accessor.string(at: o) }
|
||||
public var bannerSegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.banner.v) }
|
||||
public var displayName: String? { let o = _accessor.offset(VTOFFSET.displayName.v); return o == 0 ? nil : _accessor.string(at: o) }
|
||||
public var displayNameSegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.displayName.v) }
|
||||
public var reactions: Bool { let o = _accessor.offset(VTOFFSET.reactions.v); return o == 0 ? true : _accessor.readBuffer(of: Bool.self, at: o) }
|
||||
public var picture: String? { let o = _accessor.offset(VTOFFSET.picture.v); return o == 0 ? nil : _accessor.string(at: o) }
|
||||
public var pictureSegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.picture.v) }
|
||||
public var nip05: String? { let o = _accessor.offset(VTOFFSET.nip05.v); return o == 0 ? nil : _accessor.string(at: o) }
|
||||
public var nip05SegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.nip05.v) }
|
||||
public var damusDonation: Int32 { let o = _accessor.offset(VTOFFSET.damusDonation.v); return o == 0 ? 0 : _accessor.readBuffer(of: Int32.self, at: o) }
|
||||
public var damusDonationV2: Int32 { let o = _accessor.offset(VTOFFSET.damusDonationV2.v); return o == 0 ? 0 : _accessor.readBuffer(of: Int32.self, at: o) }
|
||||
public var lud06: String? { let o = _accessor.offset(VTOFFSET.lud06.v); return o == 0 ? nil : _accessor.string(at: o) }
|
||||
public var lud06SegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.lud06.v) }
|
||||
public static func startNdbProfile(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 12) }
|
||||
public static func add(name: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: name, at: VTOFFSET.name.p) }
|
||||
public static func add(website: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: website, at: VTOFFSET.website.p) }
|
||||
public static func add(about: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: about, at: VTOFFSET.about.p) }
|
||||
public static func add(lud16: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: lud16, at: VTOFFSET.lud16.p) }
|
||||
public static func add(banner: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: banner, at: VTOFFSET.banner.p) }
|
||||
public static func add(displayName: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: displayName, at: VTOFFSET.displayName.p) }
|
||||
public static func add(reactions: Bool, _ fbb: inout FlatBufferBuilder) { fbb.add(element: reactions, def: true,
|
||||
at: VTOFFSET.reactions.p) }
|
||||
public static func add(picture: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: picture, at: VTOFFSET.picture.p) }
|
||||
public static func add(nip05: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: nip05, at: VTOFFSET.nip05.p) }
|
||||
public static func add(damusDonation: Int32, _ fbb: inout FlatBufferBuilder) { fbb.add(element: damusDonation, def: 0, at: VTOFFSET.damusDonation.p) }
|
||||
public static func add(damusDonationV2: Int32, _ fbb: inout FlatBufferBuilder) { fbb.add(element: damusDonationV2, def: 0, at: VTOFFSET.damusDonationV2.p) }
|
||||
public static func add(lud06: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: lud06, at: VTOFFSET.lud06.p) }
|
||||
public static func endNdbProfile(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end }
|
||||
public static func createNdbProfile(
|
||||
_ fbb: inout FlatBufferBuilder,
|
||||
nameOffset name: Offset = Offset(),
|
||||
websiteOffset website: Offset = Offset(),
|
||||
aboutOffset about: Offset = Offset(),
|
||||
lud16Offset lud16: Offset = Offset(),
|
||||
bannerOffset banner: Offset = Offset(),
|
||||
displayNameOffset displayName: Offset = Offset(),
|
||||
reactions: Bool = true,
|
||||
pictureOffset picture: Offset = Offset(),
|
||||
nip05Offset nip05: Offset = Offset(),
|
||||
damusDonation: Int32 = 0,
|
||||
damusDonationV2: Int32 = 0,
|
||||
lud06Offset lud06: Offset = Offset()
|
||||
) -> Offset {
|
||||
let __start = NdbProfile.startNdbProfile(&fbb)
|
||||
NdbProfile.add(name: name, &fbb)
|
||||
NdbProfile.add(website: website, &fbb)
|
||||
NdbProfile.add(about: about, &fbb)
|
||||
NdbProfile.add(lud16: lud16, &fbb)
|
||||
NdbProfile.add(banner: banner, &fbb)
|
||||
NdbProfile.add(displayName: displayName, &fbb)
|
||||
NdbProfile.add(reactions: reactions, &fbb)
|
||||
NdbProfile.add(picture: picture, &fbb)
|
||||
NdbProfile.add(nip05: nip05, &fbb)
|
||||
NdbProfile.add(damusDonation: damusDonation, &fbb)
|
||||
NdbProfile.add(damusDonationV2: damusDonationV2, &fbb)
|
||||
NdbProfile.add(lud06: lud06, &fbb)
|
||||
return NdbProfile.endNdbProfile(&fbb, start: __start)
|
||||
}
|
||||
|
||||
public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable {
|
||||
var _v = try verifier.visitTable(at: position)
|
||||
try _v.visit(field: VTOFFSET.name.p, fieldName: "name", required: false, type: ForwardOffset<String>.self)
|
||||
try _v.visit(field: VTOFFSET.website.p, fieldName: "website", required: false, type: ForwardOffset<String>.self)
|
||||
try _v.visit(field: VTOFFSET.about.p, fieldName: "about", required: false, type: ForwardOffset<String>.self)
|
||||
try _v.visit(field: VTOFFSET.lud16.p, fieldName: "lud16", required: false, type: ForwardOffset<String>.self)
|
||||
try _v.visit(field: VTOFFSET.banner.p, fieldName: "banner", required: false, type: ForwardOffset<String>.self)
|
||||
try _v.visit(field: VTOFFSET.displayName.p, fieldName: "displayName", required: false, type: ForwardOffset<String>.self)
|
||||
try _v.visit(field: VTOFFSET.reactions.p, fieldName: "reactions", required: false, type: Bool.self)
|
||||
try _v.visit(field: VTOFFSET.picture.p, fieldName: "picture", required: false, type: ForwardOffset<String>.self)
|
||||
try _v.visit(field: VTOFFSET.nip05.p, fieldName: "nip05", required: false, type: ForwardOffset<String>.self)
|
||||
try _v.visit(field: VTOFFSET.damusDonation.p, fieldName: "damusDonation", required: false, type: Int32.self)
|
||||
try _v.visit(field: VTOFFSET.damusDonationV2.p, fieldName: "damusDonationV2", required: false, type: Int32.self)
|
||||
try _v.visit(field: VTOFFSET.lud06.p, fieldName: "lud06", required: false, type: ForwardOffset<String>.self)
|
||||
_v.finish()
|
||||
}
|
||||
}
|
||||
|
||||
extension NdbProfile: Encodable {
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case name = "name"
|
||||
case website = "website"
|
||||
case about = "about"
|
||||
case lud16 = "lud16"
|
||||
case banner = "banner"
|
||||
case displayName = "display_name"
|
||||
case reactions = "reactions"
|
||||
case picture = "picture"
|
||||
case nip05 = "nip05"
|
||||
case damusDonation = "damus_donation"
|
||||
case damusDonationV2 = "damus_donation_v2"
|
||||
case lud06 = "lud06"
|
||||
}
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encodeIfPresent(name, forKey: .name)
|
||||
try container.encodeIfPresent(website, forKey: .website)
|
||||
try container.encodeIfPresent(about, forKey: .about)
|
||||
try container.encodeIfPresent(lud16, forKey: .lud16)
|
||||
try container.encodeIfPresent(banner, forKey: .banner)
|
||||
try container.encodeIfPresent(displayName, forKey: .displayName)
|
||||
if reactions != true {
|
||||
try container.encodeIfPresent(reactions, forKey: .reactions)
|
||||
}
|
||||
try container.encodeIfPresent(picture, forKey: .picture)
|
||||
try container.encodeIfPresent(nip05, forKey: .nip05)
|
||||
if damusDonation != 0 {
|
||||
try container.encodeIfPresent(damusDonation, forKey: .damusDonation)
|
||||
}
|
||||
if damusDonationV2 != 0 {
|
||||
try container.encodeIfPresent(damusDonationV2, forKey: .damusDonationV2)
|
||||
}
|
||||
try container.encodeIfPresent(lud06, forKey: .lud06)
|
||||
}
|
||||
}
|
||||
|
||||
public struct NdbProfileRecord: FlatBufferObject, Verifiable {
|
||||
|
||||
static func validateVersion() { FlatBuffersVersion_23_5_26() }
|
||||
public var __buffer: ByteBuffer! { return _accessor.bb }
|
||||
private var _accessor: Table
|
||||
|
||||
private init(_ t: Table) { _accessor = t }
|
||||
public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) }
|
||||
|
||||
private enum VTOFFSET: VOffset {
|
||||
case profile = 4
|
||||
case receivedAt = 6
|
||||
case noteKey = 8
|
||||
case lnurl = 10
|
||||
var v: Int32 { Int32(self.rawValue) }
|
||||
var p: VOffset { self.rawValue }
|
||||
}
|
||||
|
||||
public var profile: NdbProfile? { let o = _accessor.offset(VTOFFSET.profile.v); return o == 0 ? nil : NdbProfile(_accessor.bb, o: _accessor.indirect(o + _accessor.postion)) }
|
||||
public var receivedAt: UInt64 { let o = _accessor.offset(VTOFFSET.receivedAt.v); return o == 0 ? 0 : _accessor.readBuffer(of: UInt64.self, at: o) }
|
||||
public var noteKey: UInt64 { let o = _accessor.offset(VTOFFSET.noteKey.v); return o == 0 ? 0 : _accessor.readBuffer(of: UInt64.self, at: o) }
|
||||
public var lnurl: String? { let o = _accessor.offset(VTOFFSET.lnurl.v); return o == 0 ? nil : _accessor.string(at: o) }
|
||||
public var lnurlSegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.lnurl.v) }
|
||||
public static func startNdbProfileRecord(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 4) }
|
||||
public static func add(profile: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: profile, at: VTOFFSET.profile.p) }
|
||||
public static func add(receivedAt: UInt64, _ fbb: inout FlatBufferBuilder) { fbb.add(element: receivedAt, def: 0, at: VTOFFSET.receivedAt.p) }
|
||||
public static func add(noteKey: UInt64, _ fbb: inout FlatBufferBuilder) { fbb.add(element: noteKey, def: 0, at: VTOFFSET.noteKey.p) }
|
||||
public static func add(lnurl: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: lnurl, at: VTOFFSET.lnurl.p) }
|
||||
public static func endNdbProfileRecord(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end }
|
||||
public static func createNdbProfileRecord(
|
||||
_ fbb: inout FlatBufferBuilder,
|
||||
profileOffset profile: Offset = Offset(),
|
||||
receivedAt: UInt64 = 0,
|
||||
noteKey: UInt64 = 0,
|
||||
lnurlOffset lnurl: Offset = Offset()
|
||||
) -> Offset {
|
||||
let __start = NdbProfileRecord.startNdbProfileRecord(&fbb)
|
||||
NdbProfileRecord.add(profile: profile, &fbb)
|
||||
NdbProfileRecord.add(receivedAt: receivedAt, &fbb)
|
||||
NdbProfileRecord.add(noteKey: noteKey, &fbb)
|
||||
NdbProfileRecord.add(lnurl: lnurl, &fbb)
|
||||
return NdbProfileRecord.endNdbProfileRecord(&fbb, start: __start)
|
||||
}
|
||||
|
||||
public static func verify<T>(_ verifier: inout Verifier, at position: Int, of type: T.Type) throws where T: Verifiable {
|
||||
var _v = try verifier.visitTable(at: position)
|
||||
try _v.visit(field: VTOFFSET.profile.p, fieldName: "profile", required: false, type: ForwardOffset<NdbProfile>.self)
|
||||
try _v.visit(field: VTOFFSET.receivedAt.p, fieldName: "receivedAt", required: false, type: UInt64.self)
|
||||
try _v.visit(field: VTOFFSET.noteKey.p, fieldName: "noteKey", required: false, type: UInt64.self)
|
||||
try _v.visit(field: VTOFFSET.lnurl.p, fieldName: "lnurl", required: false, type: ForwardOffset<String>.self)
|
||||
_v.finish()
|
||||
}
|
||||
}
|
||||
|
||||
extension NdbProfileRecord: Encodable {
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case profile = "profile"
|
||||
case receivedAt = "received_at"
|
||||
case noteKey = "note_key"
|
||||
case lnurl = "lnurl"
|
||||
}
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encodeIfPresent(profile, forKey: .profile)
|
||||
if receivedAt != 0 {
|
||||
try container.encodeIfPresent(receivedAt, forKey: .receivedAt)
|
||||
}
|
||||
if noteKey != 0 {
|
||||
try container.encodeIfPresent(noteKey, forKey: .noteKey)
|
||||
}
|
||||
try container.encodeIfPresent(lnurl, forKey: .lnurl)
|
||||
}
|
||||
}
|
||||
|
||||
20
nostrdb/src/bolt11/alignof.h
Normal file
20
nostrdb/src/bolt11/alignof.h
Normal file
@@ -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 */
|
||||
566
nostrdb/src/bolt11/amount.c
Normal file
566
nostrdb/src/bolt11/amount.c
Normal file
@@ -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 - (int)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 = (u32)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);
|
||||
}
|
||||
|
||||
|
||||
*/
|
||||
203
nostrdb/src/bolt11/amount.h
Normal file
203
nostrdb/src/bolt11/amount.h
Normal file
@@ -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. */
|
||||
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. */
|
||||
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. */
|
||||
bool amount_msat_add(struct amount_msat *val,
|
||||
struct amount_msat a,
|
||||
struct amount_msat b);
|
||||
bool amount_msat_sub(struct amount_msat *val,
|
||||
struct amount_msat a,
|
||||
struct amount_msat b);
|
||||
bool amount_sat_add(struct amount_sat *val,
|
||||
struct amount_sat a,
|
||||
struct amount_sat b);
|
||||
bool amount_sat_sub(struct amount_sat *val,
|
||||
struct amount_sat a,
|
||||
struct amount_sat b);
|
||||
bool amount_msat_sub_sat(struct amount_msat *val,
|
||||
struct amount_msat a,
|
||||
struct amount_sat b);
|
||||
bool amount_msat_add_sat(struct amount_msat *val,
|
||||
struct amount_msat a,
|
||||
struct amount_sat b);
|
||||
bool amount_sat_sub_msat(struct amount_msat *val,
|
||||
struct amount_sat a,
|
||||
struct amount_msat b);
|
||||
bool amount_msat_scale(struct amount_msat *val,
|
||||
struct amount_msat msat,
|
||||
double scale);
|
||||
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. */
|
||||
bool amount_msat_to_u32(struct amount_msat msat,
|
||||
u32 *millisatoshis);
|
||||
|
||||
/* Common operation: what is the HTLC fee for given feerate? Can overflow! */
|
||||
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. */
|
||||
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 */
|
||||
26
nostrdb/src/bolt11/array_size.h
Normal file
26
nostrdb/src/bolt11/array_size.h
Normal file
@@ -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 */
|
||||
217
nostrdb/src/bolt11/bech32.c
Normal file
217
nostrdb/src/bolt11/bech32.c
Normal file
@@ -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;
|
||||
}
|
||||
142
nostrdb/src/bolt11/bech32.h
Normal file
142
nostrdb/src/bolt11/bech32.h
Normal file
@@ -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 */
|
||||
|
||||
127
nostrdb/src/bolt11/bech32_util.c
Normal file
127
nostrdb/src/bolt11/bech32_util.c
Normal file
@@ -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;
|
||||
}
|
||||
28
nostrdb/src/bolt11/bech32_util.h
Normal file
28
nostrdb/src/bolt11/bech32_util.h
Normal file
@@ -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 */
|
||||
676
nostrdb/src/bolt11/bolt11.c
Normal file
676
nostrdb/src/bolt11/bolt11.c
Normal file
@@ -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 = (u32)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;
|
||||
}
|
||||
104
nostrdb/src/bolt11/bolt11.h
Normal file
104
nostrdb/src/bolt11/bolt11.h
Normal file
@@ -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 */
|
||||
40
nostrdb/src/bolt11/build_assert.h
Normal file
40
nostrdb/src/bolt11/build_assert.h
Normal file
@@ -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 */
|
||||
64
nostrdb/src/bolt11/check_type.h
Normal file
64
nostrdb/src/bolt11/check_type.h
Normal file
@@ -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 */
|
||||
145
nostrdb/src/bolt11/container_of.h
Normal file
145
nostrdb/src/bolt11/container_of.h
Normal file
@@ -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 */
|
||||
191
nostrdb/src/bolt11/cppmagic.h
Normal file
191
nostrdb/src/bolt11/cppmagic.h
Normal file
@@ -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 */
|
||||
15
nostrdb/src/bolt11/debug.h
Normal file
15
nostrdb/src/bolt11/debug.h
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
#ifndef PROTOVERSE_DEBUG_H
|
||||
#define PROTOVERSE_DEBUG_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define unusual(...) fprintf(stderr, "UNUSUAL: " __VA_ARGS__)
|
||||
|
||||
#ifdef DEBUG
|
||||
#define debug(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define debug(...)
|
||||
#endif
|
||||
|
||||
#endif /* PROTOVERSE_DEBUG_H */
|
||||
34
nostrdb/src/bolt11/error.c
Normal file
34
nostrdb/src/bolt11/error.c
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
#include "error.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
int note_error_(struct errors *errs_, struct cursor *p, const char *fmt, ...)
|
||||
{
|
||||
static char buf[512];
|
||||
struct error err;
|
||||
struct cursor *errs;
|
||||
va_list ap;
|
||||
|
||||
errs = &errs_->cur;
|
||||
|
||||
if (errs_->enabled == 0)
|
||||
return 0;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsprintf(buf, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
err.msg = buf;
|
||||
err.pos = p ? (int)(p->p - p->start) : 0;
|
||||
|
||||
if (!cursor_push_error(errs, &err)) {
|
||||
fprintf(stderr, "arena OOM when recording error, ");
|
||||
fprintf(stderr, "errs->p at %ld, remaining %ld, strlen %ld\n",
|
||||
errs->p - errs->start, errs->end - errs->p, strlen(buf));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
33
nostrdb/src/bolt11/error.h
Normal file
33
nostrdb/src/bolt11/error.h
Normal file
@@ -0,0 +1,33 @@
|
||||
|
||||
#ifndef PROTOVERSE_ERROR_H
|
||||
#define PROTOVERSE_ERROR_H
|
||||
|
||||
#include "cursor.h"
|
||||
|
||||
struct error {
|
||||
int pos;
|
||||
const char *msg;
|
||||
};
|
||||
|
||||
struct errors {
|
||||
struct cursor cur;
|
||||
int enabled;
|
||||
};
|
||||
|
||||
#define note_error(errs, p, fmt, ...) note_error_(errs, p, "%s: " fmt, __FUNCTION__, ##__VA_ARGS__)
|
||||
|
||||
static inline int cursor_push_error(struct cursor *cur, struct error *err)
|
||||
{
|
||||
return cursor_push_int(cur, err->pos) &&
|
||||
cursor_push_c_str(cur, err->msg);
|
||||
}
|
||||
|
||||
static inline int cursor_pull_error(struct cursor *cur, struct error *err)
|
||||
{
|
||||
return cursor_pull_int(cur, &err->pos) &&
|
||||
cursor_pull_c_str(cur, &err->msg);
|
||||
}
|
||||
|
||||
int note_error_(struct errors *errs, struct cursor *p, const char *fmt, ...);
|
||||
|
||||
#endif /* PROTOVERSE_ERROR_H */
|
||||
48
nostrdb/src/bolt11/hash_u5.c
Normal file
48
nostrdb/src/bolt11/hash_u5.c
Normal file
@@ -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((u32)(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((u32)(hu5->buf << (32 - hu5->num_bits)));
|
||||
|
||||
sha256_update(&hu5->hash, &be32, (hu5->num_bits + 7) / 8);
|
||||
}
|
||||
sha256_done(&hu5->hash, res);
|
||||
}
|
||||
20
nostrdb/src/bolt11/hash_u5.h
Normal file
20
nostrdb/src/bolt11/hash_u5.h
Normal file
@@ -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 */
|
||||
115
nostrdb/src/bolt11/likely.h
Normal file
115
nostrdb/src/bolt11/likely.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/* 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
|
||||
#ifndef likely
|
||||
#define likely(cond) (!!(cond))
|
||||
#endif
|
||||
#ifndef unlikely
|
||||
#define unlikely(cond) (!!(cond))
|
||||
#endif
|
||||
#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 */
|
||||
43
nostrdb/src/bolt11/list.c
Normal file
43
nostrdb/src/bolt11/list.c
Normal file
@@ -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;
|
||||
}
|
||||
842
nostrdb/src/bolt11/list.h
Normal file
842
nostrdb/src/bolt11/list.h
Normal file
@@ -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 */
|
||||
128
nostrdb/src/bolt11/mem.c
Normal file
128
nostrdb/src/bolt11/mem.c
Normal file
@@ -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
|
||||
}
|
||||
295
nostrdb/src/bolt11/mem.h
Normal file
295
nostrdb/src/bolt11/mem.h
Normal file
@@ -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 */
|
||||
64
nostrdb/src/bolt11/node_id.c
Normal file
64
nostrdb/src/bolt11/node_id.c
Normal file
@@ -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));
|
||||
}
|
||||
38
nostrdb/src/bolt11/node_id.h
Normal file
38
nostrdb/src/bolt11/node_id.h
Normal file
@@ -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 */
|
||||
43
nostrdb/src/bolt11/overflows.h
Normal file
43
nostrdb/src/bolt11/overflows.h
Normal file
@@ -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 = (u32)v;
|
||||
return *dst == v;
|
||||
}
|
||||
#endif /* LIGHTNING_COMMON_OVERFLOWS_H */
|
||||
35
nostrdb/src/bolt11/short_types.h
Normal file
35
nostrdb/src/bolt11/short_types.h
Normal file
@@ -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 */
|
||||
228
nostrdb/src/bolt11/str.h
Normal file
228
nostrdb/src/bolt11/str.h
Normal file
@@ -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 */
|
||||
30
nostrdb/src/bolt11/str_debug.h
Normal file
30
nostrdb/src/bolt11/str_debug.h
Normal file
@@ -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 */
|
||||
46
nostrdb/src/bolt11/structeq.h
Normal file
46
nostrdb/src/bolt11/structeq.h
Normal file
@@ -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 */
|
||||
126
nostrdb/src/bolt11/take.c
Normal file
126
nostrdb/src/bolt11/take.c
Normal file
@@ -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;
|
||||
}
|
||||
136
nostrdb/src/bolt11/take.h
Normal file
136
nostrdb/src/bolt11/take.h
Normal file
@@ -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 */
|
||||
972
nostrdb/src/bolt11/tal.c
Normal file
972
nostrdb/src/bolt11/tal.c
Normal file
@@ -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
|
||||
553
nostrdb/src/bolt11/tal.h
Normal file
553
nostrdb/src/bolt11/tal.h
Normal file
@@ -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 */
|
||||
315
nostrdb/src/bolt11/talstr.c
Normal file
315
nostrdb/src/bolt11/talstr.c
Normal file
@@ -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;
|
||||
}
|
||||
225
nostrdb/src/bolt11/talstr.h
Normal file
225
nostrdb/src/bolt11/talstr.h
Normal file
@@ -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 */
|
||||
134
nostrdb/src/bolt11/typesafe_cb.h
Normal file
134
nostrdb/src/bolt11/typesafe_cb.h
Normal file
@@ -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 */
|
||||
199
nostrdb/src/bolt11/utf8.c
Normal file
199
nostrdb/src/bolt11/utf8.c
Normal file
@@ -0,0 +1,199 @@
|
||||
/* MIT (BSD) license - see LICENSE file for details - taken from ccan. thanks rusty! */
|
||||
|
||||
#include "utf8.h"
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* I loved this table, so I stole it: */
|
||||
/*
|
||||
* Copyright (c) 2017 Christian Hansen <chansen@cpan.org>
|
||||
* <https://github.com/chansen/c-utf8-valid>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* UTF-8 Encoding Form
|
||||
*
|
||||
* U+0000..U+007F 0xxxxxxx <= 7 bits
|
||||
* U+0080..U+07FF 110xxxxx 10xxxxxx <= 11 bits
|
||||
* U+0800..U+FFFF 1110xxxx 10xxxxxx 10xxxxxx <= 16 bits
|
||||
* U+10000..U+10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx <= 21 bits
|
||||
*
|
||||
*
|
||||
* U+0000..U+007F 00..7F
|
||||
* N C0..C1 80..BF 1100000x 10xxxxxx
|
||||
* U+0080..U+07FF C2..DF 80..BF
|
||||
* N E0 80..9F 80..BF 11100000 100xxxxx
|
||||
* U+0800..U+0FFF E0 A0..BF 80..BF
|
||||
* U+1000..U+CFFF E1..EC 80..BF 80..BF
|
||||
* U+D000..U+D7FF ED 80..9F 80..BF
|
||||
* S ED A0..BF 80..BF 11101101 101xxxxx
|
||||
* U+E000..U+FFFF EE..EF 80..BF 80..BF
|
||||
* N F0 80..8F 80..BF 80..BF 11110000 1000xxxx
|
||||
* U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
|
||||
* U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
|
||||
* U+100000..U+10FFFF F4 80..8F 80..BF 80..BF 11110100 1000xxxx
|
||||
*
|
||||
* Legend:
|
||||
* N = Non-shortest form
|
||||
* S = Surrogates
|
||||
*/
|
||||
bool utf8_decode(struct utf8_state *utf8_state, char c)
|
||||
{
|
||||
if (utf8_state->used_len == utf8_state->total_len) {
|
||||
utf8_state->used_len = 1;
|
||||
/* First character in sequence. */
|
||||
if (((unsigned char)c & 0x80) == 0) {
|
||||
/* ASCII, easy. */
|
||||
if (c == 0)
|
||||
goto bad_encoding;
|
||||
utf8_state->total_len = 1;
|
||||
utf8_state->c = c;
|
||||
goto finished_decoding;
|
||||
} else if (((unsigned char)c & 0xE0) == 0xC0) {
|
||||
utf8_state->total_len = 2;
|
||||
utf8_state->c = ((unsigned char)c & 0x1F);
|
||||
return false;
|
||||
} else if (((unsigned char)c & 0xF0) == 0xE0) {
|
||||
utf8_state->total_len = 3;
|
||||
utf8_state->c = ((unsigned char)c & 0x0F);
|
||||
return false;
|
||||
} else if (((unsigned char)c & 0xF8) == 0xF0) {
|
||||
utf8_state->total_len = 4;
|
||||
utf8_state->c = ((unsigned char)c & 0x07);
|
||||
return false;
|
||||
}
|
||||
goto bad_encoding;
|
||||
}
|
||||
|
||||
if (((unsigned char)c & 0xC0) != 0x80)
|
||||
goto bad_encoding;
|
||||
|
||||
utf8_state->c <<= 6;
|
||||
utf8_state->c |= ((unsigned char)c & 0x3F);
|
||||
|
||||
utf8_state->used_len++;
|
||||
if (utf8_state->used_len == utf8_state->total_len)
|
||||
goto finished_decoding;
|
||||
return false;
|
||||
|
||||
finished_decoding:
|
||||
if (utf8_state->c == 0 || utf8_state->c > 0x10FFFF)
|
||||
errno = ERANGE;
|
||||
/* The UTF-16 "surrogate range": illegal in UTF-8 */
|
||||
else if (utf8_state->total_len == 3
|
||||
&& (utf8_state->c & 0xFFFFF800) == 0x0000D800)
|
||||
errno = ERANGE;
|
||||
else {
|
||||
int min_bits;
|
||||
switch (utf8_state->total_len) {
|
||||
case 1:
|
||||
min_bits = 0;
|
||||
break;
|
||||
case 2:
|
||||
min_bits = 7;
|
||||
break;
|
||||
case 3:
|
||||
min_bits = 11;
|
||||
break;
|
||||
case 4:
|
||||
min_bits = 16;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
if ((utf8_state->c >> min_bits) == 0)
|
||||
errno = EFBIG;
|
||||
else
|
||||
errno = 0;
|
||||
}
|
||||
return true;
|
||||
|
||||
bad_encoding:
|
||||
utf8_state->total_len = utf8_state->used_len;
|
||||
errno = EINVAL;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t utf8_encode(uint32_t point, char dest[UTF8_MAX_LEN])
|
||||
{
|
||||
if ((point >> 7) == 0) {
|
||||
if (point == 0) {
|
||||
errno = ERANGE;
|
||||
return 0;
|
||||
}
|
||||
/* 0xxxxxxx */
|
||||
dest[0] = point;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((point >> 11) == 0) {
|
||||
/* 110xxxxx 10xxxxxx */
|
||||
dest[1] = 0x80 | (point & 0x3F);
|
||||
dest[0] = 0xC0 | (point >> 6);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if ((point >> 16) == 0) {
|
||||
if (point >= 0xD800 && point <= 0xDFFF) {
|
||||
errno = ERANGE;
|
||||
return 0;
|
||||
}
|
||||
/* 1110xxxx 10xxxxxx 10xxxxxx */
|
||||
dest[2] = 0x80 | (point & 0x3F);
|
||||
dest[1] = 0x80 | ((point >> 6) & 0x3F);
|
||||
dest[0] = 0xE0 | (point >> 12);
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (point > 0x10FFFF) {
|
||||
errno = ERANGE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
|
||||
dest[3] = 0x80 | (point & 0x3F);
|
||||
dest[2] = 0x80 | ((point >> 6) & 0x3F);
|
||||
dest[1] = 0x80 | ((point >> 12) & 0x3F);
|
||||
dest[0] = 0xF0 | (point >> 18);
|
||||
return 4;
|
||||
}
|
||||
|
||||
/* Check for valid UTF-8 */
|
||||
bool utf8_check(const void *vbuf, size_t buflen)
|
||||
{
|
||||
const unsigned char *buf = vbuf;
|
||||
struct utf8_state utf8_state = UTF8_STATE_INIT;
|
||||
bool need_more = false;
|
||||
|
||||
for (size_t i = 0; i < buflen; i++) {
|
||||
if (!utf8_decode(&utf8_state, buf[i])) {
|
||||
need_more = true;
|
||||
continue;
|
||||
}
|
||||
need_more = false;
|
||||
if (errno != 0)
|
||||
return false;
|
||||
}
|
||||
return !need_more;
|
||||
}
|
||||
|
||||
57
nostrdb/src/bolt11/utf8.h
Normal file
57
nostrdb/src/bolt11/utf8.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/* MIT (BSD) license - see LICENSE file for details */
|
||||
#ifndef CCAN_UTF8_H
|
||||
#define CCAN_UTF8_H
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Unicode is limited to 21 bits. */
|
||||
#define UTF8_MAX_LEN 4
|
||||
|
||||
struct utf8_state {
|
||||
/* How many characters we are expecting as part of this Unicode point */
|
||||
uint16_t total_len;
|
||||
/* How many characters we've already seen. */
|
||||
uint16_t used_len;
|
||||
/* Compound character, aka Unicode point. */
|
||||
uint32_t c;
|
||||
};
|
||||
|
||||
#define UTF8_STATE_INIT { 0, 0, 0 }
|
||||
|
||||
static inline void utf8_state_init(struct utf8_state *utf8_state)
|
||||
{
|
||||
memset(utf8_state, 0, sizeof(*utf8_state));
|
||||
}
|
||||
|
||||
/**
|
||||
* utf8_decode - continue UTF8 decoding with this character.
|
||||
* @utf8_state - initialized UTF8 state.
|
||||
* @c - the character.
|
||||
*
|
||||
* Returns false if it needs another character to give results.
|
||||
* Otherwise returns true, @utf8_state can be reused without initializeation,
|
||||
* and sets errno:
|
||||
* 0: success
|
||||
* EINVAL: bad encoding (including a NUL character).
|
||||
* EFBIG: not a minimal encoding.
|
||||
* ERANGE: encoding of invalid character.
|
||||
*
|
||||
* You can extract the character from @utf8_state->c; @utf8_state->used_len
|
||||
* indicates how many characters have been consumed.
|
||||
*/
|
||||
bool utf8_decode(struct utf8_state *utf8_state, char c);
|
||||
|
||||
/**
|
||||
* utf8_encode - encode a point into UTF8.
|
||||
* @point - Unicode point to include.
|
||||
* @dest - buffer to fill.
|
||||
*
|
||||
* Returns 0 if point was invalid, otherwise bytes of dest used.
|
||||
* Sets errno to ERANGE if point was invalid.
|
||||
*/
|
||||
size_t utf8_encode(uint32_t point, char dest[UTF8_MAX_LEN]);
|
||||
|
||||
/* Check for valid UTF-8 */
|
||||
bool utf8_check(const void *vbuf, size_t buflen);
|
||||
#endif /* CCAN_UTF8_H */
|
||||
323
nostrdb/src/compiler.h
Normal file
323
nostrdb/src/compiler.h
Normal file
@@ -0,0 +1,323 @@
|
||||
/* CC0 (Public domain) - see LICENSE file for details */
|
||||
#ifndef CCAN_COMPILER_H
|
||||
#define CCAN_COMPILER_H
|
||||
#include "config.h"
|
||||
|
||||
#if HAVE_UNALIGNED_ACCESS
|
||||
#define alignment_ok(p, n) 1
|
||||
#else
|
||||
#define alignment_ok(p, n) ((size_t)(p) % (n) == 0)
|
||||
#endif
|
||||
|
||||
#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 */
|
||||
18
nostrdb/src/config.h
Normal file
18
nostrdb/src/config.h
Normal file
@@ -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 1
|
||||
#define HAVE_BSWAP_64 1
|
||||
#define HAVE_LITTLE_ENDIAN 1
|
||||
#endif /* CCAN_CONFIG_H */
|
||||
1110
nostrdb/src/configurator.c
Normal file
1110
nostrdb/src/configurator.c
Normal file
File diff suppressed because it is too large
Load Diff
34
nostrdb/src/cpu.h
Normal file
34
nostrdb/src/cpu.h
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <windows.h>
|
||||
#elif defined(__linux__)
|
||||
#include <unistd.h>
|
||||
#elif defined(__APPLE__)
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#else
|
||||
#error "Unsupported platform"
|
||||
#endif
|
||||
|
||||
static inline int get_cpu_cores() {
|
||||
int num_cores = 0;
|
||||
|
||||
// Windows
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
SYSTEM_INFO sysinfo;
|
||||
GetSystemInfo(&sysinfo);
|
||||
num_cores = sysinfo.dwNumberOfProcessors; // This returns logical processors
|
||||
// Further use GetLogicalProcessorInformation for physical cores...
|
||||
// Linux
|
||||
#elif defined(__linux__)
|
||||
num_cores = sysconf(_SC_NPROCESSORS_ONLN); // This returns logical processors
|
||||
// macOS
|
||||
#elif defined(__APPLE__)
|
||||
size_t size = sizeof(num_cores);
|
||||
sysctlbyname("hw.physicalcpu", &num_cores, &size, NULL, 0);
|
||||
#else
|
||||
num_cores = -1; // Unsupported platform
|
||||
#endif
|
||||
|
||||
return num_cores;
|
||||
}
|
||||
707
nostrdb/src/cursor.h
Normal file
707
nostrdb/src/cursor.h
Normal file
@@ -0,0 +1,707 @@
|
||||
|
||||
#ifndef JB55_CURSOR_H
|
||||
#define JB55_CURSOR_H
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "bolt11/likely.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
struct cursor {
|
||||
unsigned char *start;
|
||||
unsigned char *p;
|
||||
unsigned char *end;
|
||||
};
|
||||
|
||||
struct array {
|
||||
struct cursor cur;
|
||||
unsigned int elem_size;
|
||||
};
|
||||
|
||||
static inline void reset_cursor(struct cursor *cursor)
|
||||
{
|
||||
cursor->p = cursor->start;
|
||||
}
|
||||
|
||||
static inline void wipe_cursor(struct cursor *cursor)
|
||||
{
|
||||
reset_cursor(cursor);
|
||||
memset(cursor->start, 0, cursor->end - cursor->start);
|
||||
}
|
||||
|
||||
static inline void make_cursor(u8 *start, u8 *end, struct cursor *cursor)
|
||||
{
|
||||
cursor->start = start;
|
||||
cursor->p = start;
|
||||
cursor->end = end;
|
||||
}
|
||||
|
||||
static inline void make_array(struct array *a, u8* start, u8 *end, unsigned int elem_size)
|
||||
{
|
||||
make_cursor(start, end, &a->cur);
|
||||
a->elem_size = elem_size;
|
||||
}
|
||||
|
||||
static inline int cursor_eof(struct cursor *c)
|
||||
{
|
||||
return c->p == c->end;
|
||||
}
|
||||
|
||||
static inline void *cursor_malloc(struct cursor *mem, unsigned long size)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
if (mem->p + size > mem->end) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = mem->p;
|
||||
mem->p += size;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void *cursor_alloc(struct cursor *mem, unsigned long size)
|
||||
{
|
||||
void *ret;
|
||||
if (!(ret = cursor_malloc(mem, size))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(ret, 0, size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int cursor_slice(struct cursor *mem, struct cursor *slice, size_t size)
|
||||
{
|
||||
u8 *p;
|
||||
if (!(p = cursor_alloc(mem, size))) {
|
||||
return 0;
|
||||
}
|
||||
make_cursor(p, mem->p, slice);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static inline void copy_cursor(struct cursor *src, struct cursor *dest)
|
||||
{
|
||||
dest->start = src->start;
|
||||
dest->p = src->p;
|
||||
dest->end = src->end;
|
||||
}
|
||||
|
||||
static inline int cursor_skip(struct cursor *cursor, int n)
|
||||
{
|
||||
if (cursor->p + n >= cursor->end)
|
||||
return 0;
|
||||
|
||||
cursor->p += n;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int pull_byte(struct cursor *cursor, u8 *c)
|
||||
{
|
||||
if (unlikely(cursor->p >= cursor->end))
|
||||
return 0;
|
||||
|
||||
*c = *cursor->p;
|
||||
cursor->p++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int parse_byte(struct cursor *cursor, u8 *c)
|
||||
{
|
||||
if (unlikely(cursor->p >= cursor->end))
|
||||
return 0;
|
||||
|
||||
*c = *cursor->p;
|
||||
//cursor->p++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int parse_char(struct cursor *cur, char c) {
|
||||
if (cur->p >= cur->end)
|
||||
return 0;
|
||||
|
||||
if (*cur->p == c) {
|
||||
cur->p++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int peek_char(struct cursor *cur, int ind) {
|
||||
if ((cur->p + ind < cur->start) || (cur->p + ind >= cur->end))
|
||||
return -1;
|
||||
|
||||
return *(cur->p + ind);
|
||||
}
|
||||
|
||||
static inline int cursor_pull_c_str(struct cursor *cursor, const char **str)
|
||||
{
|
||||
*str = (const char*)cursor->p;
|
||||
|
||||
for (; cursor->p < cursor->end; cursor->p++) {
|
||||
if (*cursor->p == 0) {
|
||||
cursor->p++;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static inline int cursor_push_byte(struct cursor *cursor, u8 c)
|
||||
{
|
||||
if (unlikely(cursor->p + 1 > cursor->end)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*cursor->p = c;
|
||||
cursor->p++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int cursor_pull(struct cursor *cursor, u8 *data, int len)
|
||||
{
|
||||
if (unlikely(cursor->p + len > cursor->end)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(data, cursor->p, len);
|
||||
cursor->p += len;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int pull_data_into_cursor(struct cursor *cursor,
|
||||
struct cursor *dest,
|
||||
unsigned char **data,
|
||||
int len)
|
||||
{
|
||||
int ok;
|
||||
|
||||
if (unlikely(dest->p + len > dest->end)) {
|
||||
printf("not enough room in dest buffer\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ok = cursor_pull(cursor, dest->p, len);
|
||||
if (!ok) return 0;
|
||||
|
||||
*data = dest->p;
|
||||
dest->p += len;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int cursor_dropn(struct cursor *cur, int size, int n)
|
||||
{
|
||||
if (n == 0)
|
||||
return 1;
|
||||
|
||||
if (unlikely(cur->p - size*n < cur->start)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
cur->p -= size*n;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int cursor_drop(struct cursor *cur, int size)
|
||||
{
|
||||
return cursor_dropn(cur, size, 1);
|
||||
}
|
||||
|
||||
static inline unsigned char *cursor_topn(struct cursor *cur, int len, int n)
|
||||
{
|
||||
n += 1;
|
||||
if (unlikely(cur->p - len*n < cur->start)) {
|
||||
return NULL;
|
||||
}
|
||||
return cur->p - len*n;
|
||||
}
|
||||
|
||||
static inline unsigned char *cursor_top(struct cursor *cur, int len)
|
||||
{
|
||||
if (unlikely(cur->p - len < cur->start)) {
|
||||
return NULL;
|
||||
}
|
||||
return cur->p - len;
|
||||
}
|
||||
|
||||
static inline int cursor_top_int(struct cursor *cur, int *i)
|
||||
{
|
||||
u8 *p;
|
||||
if (unlikely(!(p = cursor_top(cur, sizeof(*i))))) {
|
||||
return 0;
|
||||
}
|
||||
*i = *((int*)p);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int cursor_pop(struct cursor *cur, u8 *data, int len)
|
||||
{
|
||||
if (unlikely(cur->p - len < cur->start)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
cur->p -= len;
|
||||
memcpy(data, cur->p, len);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int cursor_push(struct cursor *cursor, u8 *data, int len)
|
||||
{
|
||||
if (unlikely(cursor->p + len >= cursor->end)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cursor->p != data)
|
||||
memcpy(cursor->p, data, len);
|
||||
|
||||
cursor->p += len;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int cursor_push_int(struct cursor *cursor, int i)
|
||||
{
|
||||
return cursor_push(cursor, (u8*)&i, sizeof(i));
|
||||
}
|
||||
|
||||
static inline size_t cursor_count(struct cursor *cursor, size_t elem_size)
|
||||
{
|
||||
return (cursor->p - cursor->start)/elem_size;
|
||||
}
|
||||
|
||||
/* TODO: push_varint */
|
||||
static inline int push_varint(struct cursor *cursor, int n)
|
||||
{
|
||||
int ok, len;
|
||||
unsigned char b;
|
||||
len = 0;
|
||||
|
||||
while (1) {
|
||||
b = (n & 0xFF) | 0x80;
|
||||
n >>= 7;
|
||||
if (n == 0) {
|
||||
b &= 0x7F;
|
||||
ok = cursor_push_byte(cursor, b);
|
||||
len++;
|
||||
if (!ok) return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
ok = cursor_push_byte(cursor, b);
|
||||
len++;
|
||||
if (!ok) return 0;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/* TODO: pull_varint */
|
||||
static inline int pull_varint(struct cursor *cursor, int *n)
|
||||
{
|
||||
int ok, i;
|
||||
unsigned char b;
|
||||
*n = 0;
|
||||
|
||||
for (i = 0;; i++) {
|
||||
ok = pull_byte(cursor, &b);
|
||||
if (!ok) return 0;
|
||||
|
||||
*n |= ((int)b & 0x7F) << (i * 7);
|
||||
|
||||
/* is_last */
|
||||
if ((b & 0x80) == 0) {
|
||||
return i+1;
|
||||
}
|
||||
|
||||
if (i == 4) return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int cursor_pull_int(struct cursor *cursor, int *i)
|
||||
{
|
||||
return cursor_pull(cursor, (u8*)i, sizeof(*i));
|
||||
}
|
||||
|
||||
static inline int cursor_push_u32(struct cursor *cursor, uint32_t i) {
|
||||
return cursor_push(cursor, (unsigned char*)&i, sizeof(i));
|
||||
}
|
||||
|
||||
static inline int cursor_push_u16(struct cursor *cursor, u16 i)
|
||||
{
|
||||
return cursor_push(cursor, (u8*)&i, sizeof(i));
|
||||
}
|
||||
|
||||
static inline void *index_cursor(struct cursor *cursor, unsigned int index, int elem_size)
|
||||
{
|
||||
u8 *p;
|
||||
p = &cursor->start[elem_size * index];
|
||||
|
||||
if (unlikely(p >= cursor->end))
|
||||
return NULL;
|
||||
|
||||
return (void*)p;
|
||||
}
|
||||
|
||||
|
||||
static inline int push_sized_str(struct cursor *cursor, const char *str, int len)
|
||||
{
|
||||
return cursor_push(cursor, (u8*)str, len);
|
||||
}
|
||||
|
||||
static inline int cursor_push_lowercase(struct cursor *cur, const char *str, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (unlikely(cur->p + len >= cur->end))
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
cur->p[i] = tolower(str[i]);
|
||||
|
||||
cur->p += len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int cursor_push_str(struct cursor *cursor, const char *str)
|
||||
{
|
||||
return cursor_push(cursor, (u8*)str, (int)strlen(str));
|
||||
}
|
||||
|
||||
static inline int cursor_push_c_str(struct cursor *cursor, const char *str)
|
||||
{
|
||||
return cursor_push_str(cursor, str) && cursor_push_byte(cursor, 0);
|
||||
}
|
||||
|
||||
/* TODO: push varint size */
|
||||
static inline int push_prefixed_str(struct cursor *cursor, const char *str)
|
||||
{
|
||||
int ok, len;
|
||||
len = (int)strlen(str);
|
||||
ok = push_varint(cursor, len);
|
||||
if (!ok) return 0;
|
||||
return push_sized_str(cursor, str, len);
|
||||
}
|
||||
|
||||
static inline int pull_prefixed_str(struct cursor *cursor, struct cursor *dest_buf, const char **str)
|
||||
{
|
||||
int len, ok;
|
||||
|
||||
ok = pull_varint(cursor, &len);
|
||||
if (!ok) return 0;
|
||||
|
||||
if (unlikely(dest_buf->p + len > dest_buf->end)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ok = pull_data_into_cursor(cursor, dest_buf, (unsigned char**)str, len);
|
||||
if (!ok) return 0;
|
||||
|
||||
ok = cursor_push_byte(dest_buf, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int cursor_remaining_capacity(struct cursor *cursor)
|
||||
{
|
||||
return (int)(cursor->end - cursor->p);
|
||||
}
|
||||
|
||||
|
||||
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||||
static inline void cursor_print_around(struct cursor *cur, int range)
|
||||
{
|
||||
unsigned char *c;
|
||||
|
||||
printf("[%ld/%ld]\n", cur->p - cur->start, cur->end - cur->start);
|
||||
|
||||
c = max(cur->p - range, cur->start);
|
||||
for (; c < cur->end && c < (cur->p + range); c++) {
|
||||
printf("%02x", *c);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
c = max(cur->p - range, cur->start);
|
||||
for (; c < cur->end && c < (cur->p + range); c++) {
|
||||
if (c == cur->p) {
|
||||
printf("^");
|
||||
continue;
|
||||
}
|
||||
printf(" ");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#undef max
|
||||
|
||||
static inline int pull_bytes(struct cursor *cur, int count, const u8 **bytes) {
|
||||
if (cur->p + count > cur->end)
|
||||
return 0;
|
||||
|
||||
*bytes = cur->p;
|
||||
cur->p += count;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int parse_str(struct cursor *cur, const char *str) {
|
||||
char c, cs;
|
||||
unsigned long i, len;
|
||||
|
||||
len = strlen(str);
|
||||
|
||||
if (cur->p + len >= cur->end)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
c = tolower(cur->p[i]);
|
||||
cs = tolower(str[i]);
|
||||
|
||||
if (c != cs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
cur->p += len;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int is_whitespace(char c) {
|
||||
return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r';
|
||||
}
|
||||
|
||||
static inline int is_underscore(char c) {
|
||||
return c == '_';
|
||||
}
|
||||
|
||||
static inline int is_utf8_byte(u8 c) {
|
||||
return c & 0x80;
|
||||
}
|
||||
|
||||
static inline int parse_utf8_char(struct cursor *cursor, unsigned int *code_point, unsigned int *utf8_length)
|
||||
{
|
||||
u8 first_byte;
|
||||
if (!parse_byte(cursor, &first_byte))
|
||||
return 0; // Not enough data
|
||||
|
||||
// Determine the number of bytes in this UTF-8 character
|
||||
int remaining_bytes = 0;
|
||||
if (first_byte < 0x80) {
|
||||
*code_point = first_byte;
|
||||
return 1;
|
||||
} else if ((first_byte & 0xE0) == 0xC0) {
|
||||
remaining_bytes = 1;
|
||||
*utf8_length = remaining_bytes + 1;
|
||||
*code_point = first_byte & 0x1F;
|
||||
} else if ((first_byte & 0xF0) == 0xE0) {
|
||||
remaining_bytes = 2;
|
||||
*utf8_length = remaining_bytes + 1;
|
||||
*code_point = first_byte & 0x0F;
|
||||
} else if ((first_byte & 0xF8) == 0xF0) {
|
||||
remaining_bytes = 3;
|
||||
*utf8_length = remaining_bytes + 1;
|
||||
*code_point = first_byte & 0x07;
|
||||
} else {
|
||||
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);
|
||||
*code_point = ((first_byte & 0xF0) << 6); // Prevent testing as punctuation
|
||||
return 0; // Invalid first byte
|
||||
}
|
||||
|
||||
// Peek at remaining bytes
|
||||
for (int i = 0; i < remaining_bytes; ++i) {
|
||||
signed char next_byte;
|
||||
if ((next_byte = peek_char(cursor, i+1)) == -1) {
|
||||
*utf8_length = 1;
|
||||
return 0; // Not enough data
|
||||
}
|
||||
|
||||
// Debugging lines
|
||||
//printf("Cursor: %s\n", cursor->p);
|
||||
//printf("Codepoint: %x\n", *code_point);
|
||||
//printf("Codepoint <<6: %x\n", ((*code_point << 6) | (next_byte & 0x3F)));
|
||||
//printf("Remaining bytes: %x\n", remaining_bytes);
|
||||
//printf("First byte: %x\n", first_byte);
|
||||
//printf("Next byte: %x\n", next_byte);
|
||||
//printf("Bitwise AND result: %x\n", (next_byte & 0xC0));
|
||||
|
||||
if ((next_byte & 0xC0) != 0x80) {
|
||||
*utf8_length = 1;
|
||||
return 0; // Invalid byte in sequence
|
||||
}
|
||||
|
||||
*code_point = (*code_point << 6) | (next_byte & 0x3F);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given Unicode code point is a punctuation character
|
||||
*
|
||||
* @param codepoint The Unicode code point to check. @return true if the
|
||||
* code point is a punctuation character, false otherwise.
|
||||
*/
|
||||
static inline int is_punctuation(unsigned int codepoint) {
|
||||
|
||||
// Check for underscore (underscore is not treated as punctuation)
|
||||
if (is_underscore(codepoint))
|
||||
return 0;
|
||||
|
||||
// Check for ASCII punctuation
|
||||
if (codepoint <= 128 && ispunct(codepoint))
|
||||
return 1;
|
||||
|
||||
// Check for Unicode punctuation exceptions (punctuation allowed in hashtags)
|
||||
if (codepoint == 0x301C || codepoint == 0xFF5E) // Japanese Wave Dash / Tilde
|
||||
return 0;
|
||||
|
||||
// Check for Unicode punctuation
|
||||
// NOTE: We may need to adjust the codepoint ranges in the future,
|
||||
// to include/exclude certain types of Unicode characters in hashtags.
|
||||
// Unicode Blocks Reference: https://www.compart.com/en/unicode/block
|
||||
return (
|
||||
// Latin-1 Supplement No-Break Space (NBSP): U+00A0
|
||||
(codepoint == 0x00A0) ||
|
||||
|
||||
// Latin-1 Supplement Punctuation: U+00A1 to U+00BF
|
||||
(codepoint >= 0x00A1 && codepoint <= 0x00BF) ||
|
||||
|
||||
// General Punctuation: U+2000 to U+206F
|
||||
(codepoint >= 0x2000 && codepoint <= 0x206F) ||
|
||||
|
||||
// Currency Symbols: U+20A0 to U+20CF
|
||||
(codepoint >= 0x20A0 && codepoint <= 0x20CF) ||
|
||||
|
||||
// Supplemental Punctuation: U+2E00 to U+2E7F
|
||||
(codepoint >= 0x2E00 && codepoint <= 0x2E7F) ||
|
||||
|
||||
// CJK Symbols and Punctuation: U+3000 to U+303F
|
||||
(codepoint >= 0x3000 && codepoint <= 0x303F) ||
|
||||
|
||||
// Ideographic Description Characters: U+2FF0 to U+2FFF
|
||||
(codepoint >= 0x2FF0 && codepoint <= 0x2FFF)
|
||||
);
|
||||
}
|
||||
|
||||
static inline int is_right_boundary(int c) {
|
||||
return is_whitespace(c) || is_punctuation(c);
|
||||
}
|
||||
|
||||
static inline int is_left_boundary(char c) {
|
||||
return is_right_boundary(c) || is_utf8_byte(c);
|
||||
}
|
||||
|
||||
static inline int is_alphanumeric(char c) {
|
||||
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9');
|
||||
}
|
||||
|
||||
static inline int consume_until_boundary(struct cursor *cur) {
|
||||
unsigned int c;
|
||||
unsigned int char_length = 1;
|
||||
unsigned int *utf8_char_length = &char_length;
|
||||
|
||||
while (cur->p < cur->end) {
|
||||
c = *cur->p;
|
||||
|
||||
*utf8_char_length = 1;
|
||||
|
||||
if (is_whitespace(c))
|
||||
return 1;
|
||||
|
||||
// Need to check for UTF-8 characters, which can be multiple bytes long
|
||||
if (is_utf8_byte(c)) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_right_boundary(c))
|
||||
return 1;
|
||||
|
||||
// Need to use a variable character byte length for UTF-8 (2-4 bytes)
|
||||
if (cur->p + *utf8_char_length <= cur->end)
|
||||
cur->p += *utf8_char_length;
|
||||
else
|
||||
cur->p++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int consume_until_whitespace(struct cursor *cur, int or_end) {
|
||||
char c;
|
||||
int consumedAtLeastOne = 0;
|
||||
|
||||
while (cur->p < cur->end) {
|
||||
c = *cur->p;
|
||||
|
||||
if (is_whitespace(c))
|
||||
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;
|
||||
|
||||
while (cur->p < cur->end) {
|
||||
c = *cur->p;
|
||||
|
||||
if (!is_alphanumeric(c))
|
||||
return consumedAtLeastOne;
|
||||
|
||||
cur->p++;
|
||||
consumedAtLeastOne = 1;
|
||||
}
|
||||
|
||||
return or_end;
|
||||
}
|
||||
|
||||
|
||||
static inline int cursor_memset(struct cursor *cursor, unsigned char c, int n)
|
||||
{
|
||||
if (cursor->p + n >= cursor->end)
|
||||
return 0;
|
||||
|
||||
memset(cursor->p, c, n);
|
||||
cursor->p += 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
|
||||
365
nostrdb/src/endian.h
Normal file
365
nostrdb/src/endian.h
Normal file
@@ -0,0 +1,365 @@
|
||||
/* CC0 (Public domain) */
|
||||
#ifndef CCAN_ENDIAN_H
|
||||
#define CCAN_ENDIAN_H
|
||||
#include <stdint.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "cursor.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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 /* CCAN_ENDIAN_H */
|
||||
|
||||
68
nostrdb/src/hex.h
Normal file
68
nostrdb/src/hex.h
Normal file
@@ -0,0 +1,68 @@
|
||||
|
||||
#ifndef HEX_H
|
||||
#define HEX_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static const char hex_table[256] = {
|
||||
['0'] = 0, ['1'] = 1, ['2'] = 2, ['3'] = 3,
|
||||
['4'] = 4, ['5'] = 5, ['6'] = 6, ['7'] = 7,
|
||||
['8'] = 8, ['9'] = 9, ['a'] = 10, ['b'] = 11,
|
||||
['c'] = 12, ['d'] = 13, ['e'] = 14, ['f'] = 15,
|
||||
['A'] = 10, ['B'] = 11, ['C'] = 12, ['D'] = 13,
|
||||
['E'] = 14, ['F'] = 15
|
||||
};
|
||||
|
||||
static inline int char_to_hex(unsigned char *val, unsigned char c)
|
||||
{
|
||||
if (hex_table[c] || c == '0') {
|
||||
*val = hex_table[c];
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int 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 0;
|
||||
if (!bufsize)
|
||||
return 0;
|
||||
*(p++) = (v1 << 4) | v2;
|
||||
str += 2;
|
||||
slen -= 2;
|
||||
bufsize--;
|
||||
}
|
||||
return slen == 0 && bufsize == 0;
|
||||
}
|
||||
|
||||
|
||||
static inline char hexchar(unsigned int val)
|
||||
{
|
||||
if (val < 10)
|
||||
return '0' + val;
|
||||
if (val < 16)
|
||||
return 'a' + val - 10;
|
||||
abort();
|
||||
}
|
||||
|
||||
static int hex_encode(const void *buf, size_t bufsize, char *dest)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
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 1;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
48
nostrdb/src/io.h
Normal file
48
nostrdb/src/io.h
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
static int read_fd(FILE *fd, unsigned char *buf, int buflen, int *written)
|
||||
{
|
||||
unsigned char *p = buf;
|
||||
int len = 0;
|
||||
*written = 0;
|
||||
|
||||
do {
|
||||
len = fread(p, 1, 4096, fd);
|
||||
*written += len;
|
||||
p += len;
|
||||
if (p > buf + buflen)
|
||||
return 0;
|
||||
} while (len == 4096);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int write_file(const char *filename, unsigned char *buf, int buflen)
|
||||
{
|
||||
FILE *file = NULL;
|
||||
int ok;
|
||||
|
||||
file = fopen(filename, "w");
|
||||
if (file == NULL)
|
||||
return 0;
|
||||
|
||||
ok = fwrite(buf, buflen, 1, file);
|
||||
fclose(file);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int read_file(const char *filename, unsigned char *buf, int buflen, int *written)
|
||||
{
|
||||
FILE *file = NULL;
|
||||
int ok;
|
||||
|
||||
file = fopen(filename, "r");
|
||||
if (file == NULL)
|
||||
return 1;
|
||||
|
||||
ok = read_fd(file, buf, buflen, written);
|
||||
fclose(file);
|
||||
return ok;
|
||||
}
|
||||
|
||||
491
nostrdb/src/jsmn.h
Normal file
491
nostrdb/src/jsmn.h
Normal file
@@ -0,0 +1,491 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Serge Zaitsev
|
||||
*
|
||||
* 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 JSMN_H
|
||||
#define JSMN_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define JSMN_PARENT_LINKS
|
||||
#define JSMN_STRICT
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef JSMN_STATIC
|
||||
#define JSMN_API static
|
||||
#else
|
||||
#define JSMN_API extern
|
||||
#endif
|
||||
|
||||
/**
|
||||
* JSON type identifier. Basic types are:
|
||||
* o Object
|
||||
* o Array
|
||||
* o String
|
||||
* o Other primitive: number, boolean (true/false) or null
|
||||
*/
|
||||
typedef enum {
|
||||
JSMN_UNDEFINED = 0,
|
||||
JSMN_OBJECT = 1 << 0,
|
||||
JSMN_ARRAY = 1 << 1,
|
||||
JSMN_STRING = 1 << 2,
|
||||
JSMN_PRIMITIVE = 1 << 3
|
||||
} jsmntype_t;
|
||||
|
||||
enum jsmnerr {
|
||||
/* Not enough tokens were provided */
|
||||
JSMN_ERROR_NOMEM = -1,
|
||||
/* Invalid character inside JSON string */
|
||||
JSMN_ERROR_INVAL = -2,
|
||||
/* The string is not a full JSON packet, more bytes expected */
|
||||
JSMN_ERROR_PART = -3
|
||||
};
|
||||
|
||||
/**
|
||||
* JSON token description.
|
||||
* type type (object, array, string etc.)
|
||||
* start start position in JSON data string
|
||||
* end end position in JSON data string
|
||||
*/
|
||||
typedef struct jsmntok {
|
||||
jsmntype_t type;
|
||||
int start;
|
||||
int end;
|
||||
int size;
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
int parent;
|
||||
#endif
|
||||
} jsmntok_t;
|
||||
|
||||
/**
|
||||
* JSON parser. Contains an array of token blocks available. Also stores
|
||||
* the string being parsed now and current position in that string.
|
||||
*/
|
||||
typedef struct jsmn_parser {
|
||||
unsigned int pos; /* offset in the JSON string */
|
||||
unsigned int toknext; /* next token to allocate */
|
||||
int toksuper; /* superior token node, e.g. parent object or array */
|
||||
} jsmn_parser;
|
||||
|
||||
/**
|
||||
* Create JSON parser over an array of tokens
|
||||
*/
|
||||
JSMN_API void jsmn_init(jsmn_parser *parser);
|
||||
|
||||
/**
|
||||
* Run JSON parser. It parses a JSON data string into and array of tokens, each
|
||||
* describing
|
||||
* a single JSON object.
|
||||
*/
|
||||
JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len,
|
||||
jsmntok_t *tokens, const unsigned int num_tokens, int stop_at_id);
|
||||
|
||||
#ifndef JSMN_HEADER
|
||||
/**
|
||||
* Allocates a fresh unused token from the token pool.
|
||||
*/
|
||||
static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, jsmntok_t *tokens,
|
||||
const size_t num_tokens) {
|
||||
jsmntok_t *tok;
|
||||
if (parser->toknext >= num_tokens) {
|
||||
return NULL;
|
||||
}
|
||||
tok = &tokens[parser->toknext++];
|
||||
tok->start = tok->end = -1;
|
||||
tok->size = 0;
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
tok->parent = -1;
|
||||
#endif
|
||||
return tok;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills token type and boundaries.
|
||||
*/
|
||||
static void jsmn_fill_token(jsmntok_t *token, const jsmntype_t type,
|
||||
const int start, const int end) {
|
||||
token->type = type;
|
||||
token->start = start;
|
||||
token->end = end;
|
||||
token->size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills next available token with JSON primitive.
|
||||
*/
|
||||
static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
|
||||
const size_t len, jsmntok_t *tokens,
|
||||
const size_t num_tokens) {
|
||||
jsmntok_t *token;
|
||||
int start;
|
||||
|
||||
start = parser->pos;
|
||||
|
||||
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
|
||||
switch (js[parser->pos]) {
|
||||
#ifndef JSMN_STRICT
|
||||
/* In strict mode primitive must be followed by "," or "}" or "]" */
|
||||
case ':':
|
||||
#endif
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
case ' ':
|
||||
case ',':
|
||||
case ']':
|
||||
case '}':
|
||||
goto found;
|
||||
default:
|
||||
/* to quiet a warning from gcc*/
|
||||
break;
|
||||
}
|
||||
if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
}
|
||||
#ifdef JSMN_STRICT
|
||||
/* In strict mode primitive must be followed by a comma/object/array */
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_PART;
|
||||
#endif
|
||||
|
||||
found:
|
||||
if (tokens == NULL) {
|
||||
parser->pos--;
|
||||
return 0;
|
||||
}
|
||||
token = jsmn_alloc_token(parser, tokens, num_tokens);
|
||||
if (token == NULL) {
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_NOMEM;
|
||||
}
|
||||
jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
token->parent = parser->toksuper;
|
||||
#endif
|
||||
parser->pos--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills next token with JSON string.
|
||||
*/
|
||||
static int jsmn_parse_string(jsmn_parser *parser, const char *js,
|
||||
const size_t len, jsmntok_t *tokens,
|
||||
const size_t num_tokens) {
|
||||
jsmntok_t *token;
|
||||
|
||||
int start = parser->pos;
|
||||
|
||||
/* Skip starting quote */
|
||||
parser->pos++;
|
||||
|
||||
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
|
||||
char c = js[parser->pos];
|
||||
|
||||
/* Quote: end of string */
|
||||
if (c == '\"') {
|
||||
if (tokens == NULL) {
|
||||
return 0;
|
||||
}
|
||||
token = jsmn_alloc_token(parser, tokens, num_tokens);
|
||||
if (token == NULL) {
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_NOMEM;
|
||||
}
|
||||
jsmn_fill_token(token, JSMN_STRING, start + 1, parser->pos);
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
token->parent = parser->toksuper;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Backslash: Quoted symbol expected */
|
||||
if (c == '\\' && parser->pos + 1 < len) {
|
||||
int i;
|
||||
parser->pos++;
|
||||
switch (js[parser->pos]) {
|
||||
/* Allowed escaped symbols */
|
||||
case '\"':
|
||||
case '/':
|
||||
case '\\':
|
||||
case 'b':
|
||||
case 'f':
|
||||
case 'r':
|
||||
case 'n':
|
||||
case 't':
|
||||
break;
|
||||
/* Allows escaped symbol \uXXXX */
|
||||
case 'u':
|
||||
parser->pos++;
|
||||
for (i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0';
|
||||
i++) {
|
||||
/* If it isn't a hex character we have an error */
|
||||
if (!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
|
||||
(js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
|
||||
(js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
parser->pos++;
|
||||
}
|
||||
parser->pos--;
|
||||
break;
|
||||
/* Unexpected symbol */
|
||||
default:
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_PART;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse JSON string and fill tokens.
|
||||
*/
|
||||
JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len,
|
||||
jsmntok_t *tokens, const unsigned int num_tokens, int stop_at_id) {
|
||||
int r, i, idkey;
|
||||
jsmntok_t *token;
|
||||
int count = parser->toknext;
|
||||
|
||||
idkey = 0;
|
||||
|
||||
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
|
||||
char c;
|
||||
jsmntype_t type;
|
||||
|
||||
c = js[parser->pos];
|
||||
switch (c) {
|
||||
case '{':
|
||||
case '[':
|
||||
count++;
|
||||
if (tokens == NULL) {
|
||||
break;
|
||||
}
|
||||
token = jsmn_alloc_token(parser, tokens, num_tokens);
|
||||
if (token == NULL) {
|
||||
return JSMN_ERROR_NOMEM;
|
||||
}
|
||||
if (parser->toksuper != -1) {
|
||||
jsmntok_t *t = &tokens[parser->toksuper];
|
||||
#ifdef JSMN_STRICT
|
||||
/* In strict mode an object or array can't become a key */
|
||||
if (t->type == JSMN_OBJECT) {
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
#endif
|
||||
t->size++;
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
token->parent = parser->toksuper;
|
||||
#endif
|
||||
}
|
||||
token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
|
||||
token->start = parser->pos;
|
||||
parser->toksuper = parser->toknext - 1;
|
||||
break;
|
||||
case '}':
|
||||
case ']':
|
||||
if (tokens == NULL) {
|
||||
break;
|
||||
}
|
||||
type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
if (parser->toknext < 1) {
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
token = &tokens[parser->toknext - 1];
|
||||
for (;;) {
|
||||
if (token->start != -1 && token->end == -1) {
|
||||
if (token->type != type) {
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
token->end = parser->pos + 1;
|
||||
parser->toksuper = token->parent;
|
||||
break;
|
||||
}
|
||||
if (token->parent == -1) {
|
||||
if (token->type != type || parser->toksuper == -1) {
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
token = &tokens[token->parent];
|
||||
}
|
||||
#else
|
||||
for (i = parser->toknext - 1; i >= 0; i--) {
|
||||
token = &tokens[i];
|
||||
if (token->start != -1 && token->end == -1) {
|
||||
if (token->type != type) {
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
parser->toksuper = -1;
|
||||
token->end = parser->pos + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Error if unmatched closing bracket */
|
||||
if (i == -1) {
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
for (; i >= 0; i--) {
|
||||
token = &tokens[i];
|
||||
if (token->start != -1 && token->end == -1) {
|
||||
parser->toksuper = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case '\"':
|
||||
r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
count++;
|
||||
if (parser->toksuper != -1 && tokens != NULL) {
|
||||
tokens[parser->toksuper].size++;
|
||||
}
|
||||
|
||||
// big hack. resumable parsing when encountering the id field
|
||||
if (stop_at_id) {
|
||||
token = &tokens[parser->toknext-1];
|
||||
if (idkey == 1 && (token->end - token->start) == 64) {
|
||||
//printf("jsmn: found id '%.*s'\n", token->end - token->start, js + token->start);
|
||||
parser->pos++;
|
||||
return -42;
|
||||
} else if (idkey == 0 && (token->end - token->start) == 2 &&
|
||||
(js + token->start)[0] == 'i' &&
|
||||
(js + token->start)[1] == 'd') {
|
||||
//printf("jsmn: found id key\n");
|
||||
idkey = 1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
case ' ':
|
||||
break;
|
||||
case ':':
|
||||
parser->toksuper = parser->toknext - 1;
|
||||
break;
|
||||
case ',':
|
||||
if (tokens != NULL && parser->toksuper != -1 &&
|
||||
tokens[parser->toksuper].type != JSMN_ARRAY &&
|
||||
tokens[parser->toksuper].type != JSMN_OBJECT) {
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
parser->toksuper = tokens[parser->toksuper].parent;
|
||||
#else
|
||||
for (i = parser->toknext - 1; i >= 0; i--) {
|
||||
if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
|
||||
if (tokens[i].start != -1 && tokens[i].end == -1) {
|
||||
parser->toksuper = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
#ifdef JSMN_STRICT
|
||||
/* In strict mode primitives are: numbers and booleans */
|
||||
case '-':
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case 't':
|
||||
case 'f':
|
||||
case 'n':
|
||||
/* And they must not be keys of the object */
|
||||
if (tokens != NULL && parser->toksuper != -1) {
|
||||
const jsmntok_t *t = &tokens[parser->toksuper];
|
||||
if (t->type == JSMN_OBJECT ||
|
||||
(t->type == JSMN_STRING && t->size != 0)) {
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* In non-strict mode every unquoted value is a primitive */
|
||||
default:
|
||||
#endif
|
||||
r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
count++;
|
||||
if (parser->toksuper != -1 && tokens != NULL) {
|
||||
tokens[parser->toksuper].size++;
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef JSMN_STRICT
|
||||
/* Unexpected char in strict mode */
|
||||
default:
|
||||
return JSMN_ERROR_INVAL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (tokens != NULL) {
|
||||
for (i = parser->toknext - 1; i >= 0; i--) {
|
||||
/* Unmatched opened object or array */
|
||||
if (tokens[i].start != -1 && tokens[i].end == -1) {
|
||||
return JSMN_ERROR_PART;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new parser based over a given buffer with an array of tokens
|
||||
* available.
|
||||
*/
|
||||
JSMN_API void jsmn_init(jsmn_parser *parser) {
|
||||
parser->pos = 0;
|
||||
parser->toknext = 0;
|
||||
parser->toksuper = -1;
|
||||
}
|
||||
|
||||
#endif /* JSMN_HEADER */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* JSMN_H */
|
||||
100
nostrdb/src/lmdb_util.h
Normal file
100
nostrdb/src/lmdb_util.h
Normal file
@@ -0,0 +1,100 @@
|
||||
|
||||
// Define callback function type
|
||||
typedef bool (*lmdb_callback_t)(const MDB_val*, const MDB_val*);
|
||||
|
||||
|
||||
int lmdb_foreach(MDB_txn *txn, MDB_dbi dbi, MDB_val *start, MDB_val *start_dup, callback_t cb, bool reverse) {
|
||||
int success = 0;
|
||||
MDB_cursor *cursor;
|
||||
|
||||
// Open a cursor on the provided transaction and database
|
||||
int rc = mdb_cursor_open(txn, dbi, &cursor);
|
||||
|
||||
if (rc != 0)
|
||||
return 0;
|
||||
|
||||
MDB_val k = *start, v = *start_dup;
|
||||
MDB_cursor_op op = reverse ? MDB_PREV : MDB_NEXT;
|
||||
|
||||
// If we're scanning in reverse...
|
||||
if (reverse) {
|
||||
// Try to position the cursor at the first key-value pair where
|
||||
// both the key and the value are greater than or equal to our
|
||||
// starting point.
|
||||
rc = mdb_cursor_get(cursor, &k, &v, MDB_GET_BOTH_RANGE);
|
||||
if (rc == 0) {
|
||||
if (v.mv_size != start_dup->mv_size ||
|
||||
memcmp(v.mv_data, start_dup->mv_data, v.mv_size) != 0) {
|
||||
// If the value doesn't match our starting
|
||||
// point, step back to the previous record.
|
||||
if (mdb_cursor_get(cursor, &k, &v, MDB_PREV) != 0)
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
// If we couldn't find a record that matches both our
|
||||
// starting key and value, try to find a record that
|
||||
// matches just our starting key.
|
||||
if (mdb_cursor_get(cursor, &k, &v, MDB_SET) == 0) {
|
||||
// If we find a match, move to the last value
|
||||
// for this key, since we're scanning in
|
||||
// reverse.
|
||||
if (mdb_cursor_get(cursor, &k, &v, MDB_LAST_DUP) != 0)
|
||||
goto cleanup;
|
||||
} else {
|
||||
// If we can't find a record with our starting
|
||||
// key, try to find the first record with a key
|
||||
// greater than our starting key.
|
||||
if (mdb_cursor_get(cursor, &k, &v, MDB_SET_RANGE) == 0) {
|
||||
// If we find such a record, step back
|
||||
// to the previous record.
|
||||
if (mdb_cursor_get(cursor, &k, &v, MDB_PREV) != 0)
|
||||
goto cleanup;
|
||||
} else {
|
||||
// If we can't even find a record with
|
||||
// a key greater than our starting key,
|
||||
// fall back to starting from the last
|
||||
// record in the database.
|
||||
if (mdb_cursor_get(cursor, &k, &v, MDB_LAST) != 0)
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If we're not scanning in reverse...
|
||||
else {
|
||||
// Try to position the cursor at the first key-value
|
||||
// pair where both the key and the value are greater
|
||||
// than or equal to our starting point.
|
||||
if (mdb_cursor_get(cursor, &k, &v, MDB_SET) != 0) {
|
||||
// If we couldn't find a record that matches
|
||||
// both our starting key and value, try to find
|
||||
// a record that matches just our starting key.
|
||||
if (mdb_cursor_get(cursor, &k, &v, MDB_SET_RANGE) != 0)
|
||||
goto cleanup;
|
||||
|
||||
// If we can't find a record with our starting
|
||||
// key, try to find the first record with a key
|
||||
// greater than our starting key.
|
||||
if (mdb_cursor_get(cursor, &k, &v, MDB_FIRST_DUP) != 0)
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Whether we're scanning forward or backward, start the actual
|
||||
// iteration, moving one step at a time in the appropriate direction
|
||||
// and calling the provided callback for each record.
|
||||
do {
|
||||
if (!cb(&k, &v))
|
||||
goto cleanup;
|
||||
} while (mdb_cursor_get(cursor, &k, &v, op) == 0);
|
||||
|
||||
// If we make it through the entire iteration without the callback
|
||||
// returning false, return true to signal success.
|
||||
success = 1;
|
||||
|
||||
cleanup:
|
||||
mdb_cursor_close(cursor);
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
72
nostrdb/src/memchr.h
Normal file
72
nostrdb/src/memchr.h
Normal file
@@ -0,0 +1,72 @@
|
||||
|
||||
|
||||
#ifndef FAST_MEMCHR_H
|
||||
#define FAST_MEMCHR_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __ARM_NEON
|
||||
#define vector_strchr neon_strchr
|
||||
#else
|
||||
#define vector_strchr native_memchr
|
||||
#endif
|
||||
|
||||
#ifdef __ARM_NEON
|
||||
#include <arm_neon.h>
|
||||
static const char *neon_strchr(const char *str, char c, size_t length) {
|
||||
const char* end = str + length;
|
||||
|
||||
// Alignment handling
|
||||
while (str < end && ((size_t)str & 0xF)) {
|
||||
if (*str == c)
|
||||
return str;
|
||||
++str;
|
||||
}
|
||||
|
||||
uint8x16_t searchChar = vdupq_n_u8(c);
|
||||
|
||||
while (str + 16 <= end) {
|
||||
uint8x16_t chunk = vld1q_u8((const uint8_t*)str);
|
||||
uint8x16_t comparison = vceqq_u8(chunk, searchChar);
|
||||
|
||||
// Check first 64 bits
|
||||
uint64_t result0 =
|
||||
vgetq_lane_u64(vreinterpretq_u64_u8(comparison), 0);
|
||||
|
||||
if (result0)
|
||||
return str + __builtin_ctzll(result0)/8;
|
||||
|
||||
// Check second 64 bits
|
||||
uint64_t result1 = vgetq_lane_u64(vreinterpretq_u64_u8(comparison), 1);
|
||||
if (result1)
|
||||
return str + 8 + __builtin_ctzll(result1)/8;
|
||||
|
||||
str += 16;
|
||||
}
|
||||
|
||||
// Handle remaining unaligned characters
|
||||
for (; str < end; ++str) {
|
||||
if (*str == c)
|
||||
return str;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline const char *native_memchr(const char *str, char c, size_t length) {
|
||||
const void *result = memchr(str, c, length);
|
||||
return (const char *) result;
|
||||
}
|
||||
|
||||
static inline const char *fast_strchr(const char *str, char c, size_t length)
|
||||
{
|
||||
if (length >= 16) {
|
||||
return vector_strchr(str, c, length);
|
||||
}
|
||||
|
||||
return native_memchr(str, c, length);
|
||||
}
|
||||
|
||||
|
||||
#endif // FAST_MEMCHR_H
|
||||
306
nostrdb/src/nostr_bech32.c
Normal file
306
nostrdb/src/nostr_bech32.c
Normal file
@@ -0,0 +1,306 @@
|
||||
//
|
||||
// nostr_bech32.c
|
||||
// damus
|
||||
//
|
||||
// Created by William Casarin on 2023-04-09.
|
||||
//
|
||||
|
||||
#include "nostr_bech32.h"
|
||||
#include <stdlib.h>
|
||||
#include "cursor.h"
|
||||
#include "bech32.h"
|
||||
|
||||
#define MAX_TLVS 16
|
||||
|
||||
#define TLV_SPECIAL 0
|
||||
#define TLV_RELAY 1
|
||||
#define TLV_AUTHOR 2
|
||||
#define TLV_KIND 3
|
||||
#define TLV_KNOWN_TLVS 4
|
||||
|
||||
struct nostr_tlv {
|
||||
u8 type;
|
||||
u8 len;
|
||||
const u8 *value;
|
||||
};
|
||||
|
||||
struct nostr_tlvs {
|
||||
struct nostr_tlv tlvs[MAX_TLVS];
|
||||
int num_tlvs;
|
||||
};
|
||||
|
||||
static int parse_nostr_tlv(struct cursor *cur, struct nostr_tlv *tlv) {
|
||||
// get the tlv tag
|
||||
if (!pull_byte(cur, &tlv->type))
|
||||
return 0;
|
||||
|
||||
// unknown, fail!
|
||||
if (tlv->type >= TLV_KNOWN_TLVS)
|
||||
return 0;
|
||||
|
||||
// get the length
|
||||
if (!pull_byte(cur, &tlv->len))
|
||||
return 0;
|
||||
|
||||
// is the reported length greater then our buffer? if so fail
|
||||
if (cur->p + tlv->len > cur->end)
|
||||
return 0;
|
||||
|
||||
tlv->value = cur->p;
|
||||
cur->p += tlv->len;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parse_nostr_tlvs(struct cursor *cur, struct nostr_tlvs *tlvs) {
|
||||
int i;
|
||||
tlvs->num_tlvs = 0;
|
||||
|
||||
for (i = 0; i < MAX_TLVS; i++) {
|
||||
if (parse_nostr_tlv(cur, &tlvs->tlvs[i])) {
|
||||
tlvs->num_tlvs++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tlvs->num_tlvs == 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int find_tlv(struct nostr_tlvs *tlvs, u8 type, struct nostr_tlv **tlv) {
|
||||
*tlv = NULL;
|
||||
|
||||
for (int i = 0; i < tlvs->num_tlvs; i++) {
|
||||
if (tlvs->tlvs[i].type == type) {
|
||||
*tlv = &tlvs->tlvs[i];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_nostr_bech32_type(const char *prefix, enum nostr_bech32_type *type) {
|
||||
// Parse type
|
||||
if (strcmp(prefix, "note") == 0) {
|
||||
*type = NOSTR_BECH32_NOTE;
|
||||
return 1;
|
||||
} else if (strcmp(prefix, "npub") == 0) {
|
||||
*type = NOSTR_BECH32_NPUB;
|
||||
return 1;
|
||||
} else if (strcmp(prefix, "nsec") == 0) {
|
||||
*type = NOSTR_BECH32_NSEC;
|
||||
return 1;
|
||||
} else if (strcmp(prefix, "nprofile") == 0) {
|
||||
*type = NOSTR_BECH32_NPROFILE;
|
||||
return 1;
|
||||
} else if (strcmp(prefix, "nevent") == 0) {
|
||||
*type = NOSTR_BECH32_NEVENT;
|
||||
return 1;
|
||||
} else if (strcmp(prefix, "nrelay") == 0) {
|
||||
*type = NOSTR_BECH32_NRELAY;
|
||||
return 1;
|
||||
} else if (strcmp(prefix, "naddr") == 0) {
|
||||
*type = NOSTR_BECH32_NADDR;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_nostr_bech32_note(struct cursor *cur, struct bech32_note *note) {
|
||||
return pull_bytes(cur, 32, ¬e->event_id);
|
||||
}
|
||||
|
||||
static int parse_nostr_bech32_npub(struct cursor *cur, struct bech32_npub *npub) {
|
||||
return pull_bytes(cur, 32, &npub->pubkey);
|
||||
}
|
||||
|
||||
static int parse_nostr_bech32_nsec(struct cursor *cur, struct bech32_nsec *nsec) {
|
||||
return pull_bytes(cur, 32, &nsec->nsec);
|
||||
}
|
||||
|
||||
static int tlvs_to_relays(struct nostr_tlvs *tlvs, struct relays *relays) {
|
||||
struct nostr_tlv *tlv;
|
||||
struct str_block *str;
|
||||
|
||||
relays->num_relays = 0;
|
||||
|
||||
for (int i = 0; i < tlvs->num_tlvs; i++) {
|
||||
tlv = &tlvs->tlvs[i];
|
||||
if (tlv->type != TLV_RELAY)
|
||||
continue;
|
||||
|
||||
if (relays->num_relays + 1 > MAX_RELAYS)
|
||||
break;
|
||||
|
||||
str = &relays->relays[relays->num_relays++];
|
||||
str->start = (const char*)tlv->value;
|
||||
str->end = (const char*)(tlv->value + tlv->len);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parse_nostr_bech32_nevent(struct cursor *cur, struct bech32_nevent *nevent) {
|
||||
struct nostr_tlvs tlvs;
|
||||
struct nostr_tlv *tlv;
|
||||
|
||||
if (!parse_nostr_tlvs(cur, &tlvs))
|
||||
return 0;
|
||||
|
||||
if (!find_tlv(&tlvs, TLV_SPECIAL, &tlv))
|
||||
return 0;
|
||||
|
||||
if (tlv->len != 32)
|
||||
return 0;
|
||||
|
||||
nevent->event_id = tlv->value;
|
||||
|
||||
if (find_tlv(&tlvs, TLV_AUTHOR, &tlv)) {
|
||||
nevent->pubkey = tlv->value;
|
||||
} else {
|
||||
nevent->pubkey = NULL;
|
||||
}
|
||||
|
||||
return tlvs_to_relays(&tlvs, &nevent->relays);
|
||||
}
|
||||
|
||||
static int parse_nostr_bech32_naddr(struct cursor *cur, struct bech32_naddr *naddr) {
|
||||
struct nostr_tlvs tlvs;
|
||||
struct nostr_tlv *tlv;
|
||||
|
||||
if (!parse_nostr_tlvs(cur, &tlvs))
|
||||
return 0;
|
||||
|
||||
if (!find_tlv(&tlvs, TLV_SPECIAL, &tlv))
|
||||
return 0;
|
||||
|
||||
naddr->identifier.start = (const char*)tlv->value;
|
||||
naddr->identifier.end = (const char*)tlv->value + tlv->len;
|
||||
|
||||
if (!find_tlv(&tlvs, TLV_AUTHOR, &tlv))
|
||||
return 0;
|
||||
|
||||
naddr->pubkey = tlv->value;
|
||||
|
||||
return tlvs_to_relays(&tlvs, &naddr->relays);
|
||||
}
|
||||
|
||||
static int parse_nostr_bech32_nprofile(struct cursor *cur, struct bech32_nprofile *nprofile) {
|
||||
struct nostr_tlvs tlvs;
|
||||
struct nostr_tlv *tlv;
|
||||
|
||||
if (!parse_nostr_tlvs(cur, &tlvs))
|
||||
return 0;
|
||||
|
||||
if (!find_tlv(&tlvs, TLV_SPECIAL, &tlv))
|
||||
return 0;
|
||||
|
||||
if (tlv->len != 32)
|
||||
return 0;
|
||||
|
||||
nprofile->pubkey = tlv->value;
|
||||
|
||||
return tlvs_to_relays(&tlvs, &nprofile->relays);
|
||||
}
|
||||
|
||||
static int parse_nostr_bech32_nrelay(struct cursor *cur, struct bech32_nrelay *nrelay) {
|
||||
struct nostr_tlvs tlvs;
|
||||
struct nostr_tlv *tlv;
|
||||
|
||||
if (!parse_nostr_tlvs(cur, &tlvs))
|
||||
return 0;
|
||||
|
||||
if (!find_tlv(&tlvs, TLV_SPECIAL, &tlv))
|
||||
return 0;
|
||||
|
||||
nrelay->relay.start = (const char*)tlv->value;
|
||||
nrelay->relay.end = (const char*)tlv->value + tlv->len;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int parse_nostr_bech32(struct cursor *cur, struct nostr_bech32 *obj) {
|
||||
u8 *start, *end;
|
||||
|
||||
start = cur->p;
|
||||
|
||||
if (!consume_until_non_alphanumeric(cur, 1)) {
|
||||
cur->p = start;
|
||||
return 0;
|
||||
}
|
||||
|
||||
end = cur->p;
|
||||
|
||||
size_t data_len;
|
||||
size_t input_len = end - start;
|
||||
if (input_len < 10 || input_len > 10000) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
obj->buffer = malloc(input_len * 2);
|
||||
if (!obj->buffer)
|
||||
return 0;
|
||||
|
||||
u8 data[input_len];
|
||||
char prefix[input_len];
|
||||
|
||||
if (bech32_decode_len(prefix, data, &data_len, (const char*)start, input_len) == BECH32_ENCODING_NONE) {
|
||||
cur->p = start;
|
||||
return 0;
|
||||
}
|
||||
|
||||
obj->buflen = 0;
|
||||
if (!bech32_convert_bits(obj->buffer, &obj->buflen, 8, data, data_len, 5, 0)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!parse_nostr_bech32_type(prefix, &obj->type)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
struct cursor bcur;
|
||||
make_cursor(obj->buffer, obj->buffer + obj->buflen, &bcur);
|
||||
|
||||
switch (obj->type) {
|
||||
case NOSTR_BECH32_NOTE:
|
||||
if (!parse_nostr_bech32_note(&bcur, &obj->data.note))
|
||||
goto fail;
|
||||
break;
|
||||
case NOSTR_BECH32_NPUB:
|
||||
if (!parse_nostr_bech32_npub(&bcur, &obj->data.npub))
|
||||
goto fail;
|
||||
break;
|
||||
case NOSTR_BECH32_NSEC:
|
||||
if (!parse_nostr_bech32_nsec(&bcur, &obj->data.nsec))
|
||||
goto fail;
|
||||
break;
|
||||
case NOSTR_BECH32_NEVENT:
|
||||
if (!parse_nostr_bech32_nevent(&bcur, &obj->data.nevent))
|
||||
goto fail;
|
||||
break;
|
||||
case NOSTR_BECH32_NADDR:
|
||||
if (!parse_nostr_bech32_naddr(&bcur, &obj->data.naddr))
|
||||
goto fail;
|
||||
break;
|
||||
case NOSTR_BECH32_NPROFILE:
|
||||
if (!parse_nostr_bech32_nprofile(&bcur, &obj->data.nprofile))
|
||||
goto fail;
|
||||
break;
|
||||
case NOSTR_BECH32_NRELAY:
|
||||
if (!parse_nostr_bech32_nrelay(&bcur, &obj->data.nrelay))
|
||||
goto fail;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
free(obj->buffer);
|
||||
cur->p = start;
|
||||
return 0;
|
||||
}
|
||||
84
nostrdb/src/nostr_bech32.h
Normal file
84
nostrdb/src/nostr_bech32.h
Normal file
@@ -0,0 +1,84 @@
|
||||
//
|
||||
// nostr_bech32.h
|
||||
// damus
|
||||
//
|
||||
// Created by William Casarin on 2023-04-09.
|
||||
//
|
||||
|
||||
#ifndef nostr_bech32_h
|
||||
#define nostr_bech32_h
|
||||
|
||||
#include <stdio.h>
|
||||
#include "str_block.h"
|
||||
#include "cursor.h"
|
||||
typedef unsigned char u8;
|
||||
#define MAX_RELAYS 10
|
||||
|
||||
struct relays {
|
||||
struct str_block relays[MAX_RELAYS];
|
||||
int num_relays;
|
||||
};
|
||||
|
||||
enum nostr_bech32_type {
|
||||
NOSTR_BECH32_NOTE = 1,
|
||||
NOSTR_BECH32_NPUB = 2,
|
||||
NOSTR_BECH32_NPROFILE = 3,
|
||||
NOSTR_BECH32_NEVENT = 4,
|
||||
NOSTR_BECH32_NRELAY = 5,
|
||||
NOSTR_BECH32_NADDR = 6,
|
||||
NOSTR_BECH32_NSEC = 7,
|
||||
};
|
||||
|
||||
struct bech32_note {
|
||||
const u8 *event_id;
|
||||
};
|
||||
|
||||
struct bech32_npub {
|
||||
const u8 *pubkey;
|
||||
};
|
||||
|
||||
struct bech32_nsec {
|
||||
const u8 *nsec;
|
||||
};
|
||||
|
||||
struct bech32_nevent {
|
||||
struct relays relays;
|
||||
const u8 *event_id;
|
||||
const u8 *pubkey; // optional
|
||||
};
|
||||
|
||||
struct bech32_nprofile {
|
||||
struct relays relays;
|
||||
const u8 *pubkey;
|
||||
};
|
||||
|
||||
struct bech32_naddr {
|
||||
struct relays relays;
|
||||
struct str_block identifier;
|
||||
const u8 *pubkey;
|
||||
};
|
||||
|
||||
struct bech32_nrelay {
|
||||
struct str_block relay;
|
||||
};
|
||||
|
||||
typedef struct nostr_bech32 {
|
||||
enum nostr_bech32_type type;
|
||||
u8 *buffer; // holds strings and tlv stuff
|
||||
size_t buflen;
|
||||
|
||||
union {
|
||||
struct bech32_note note;
|
||||
struct bech32_npub npub;
|
||||
struct bech32_nsec nsec;
|
||||
struct bech32_nevent nevent;
|
||||
struct bech32_nprofile nprofile;
|
||||
struct bech32_naddr naddr;
|
||||
struct bech32_nrelay nrelay;
|
||||
} data;
|
||||
} nostr_bech32_t;
|
||||
|
||||
|
||||
int parse_nostr_bech32(struct cursor *cur, struct nostr_bech32 *obj);
|
||||
|
||||
#endif /* nostr_bech32_h */
|
||||
4608
nostrdb/src/nostrdb.c
Normal file
4608
nostrdb/src/nostrdb.c
Normal file
File diff suppressed because it is too large
Load Diff
386
nostrdb/src/nostrdb.h
Normal file
386
nostrdb/src/nostrdb.h
Normal file
@@ -0,0 +1,386 @@
|
||||
#ifndef NOSTRDB_H
|
||||
#define NOSTRDB_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "cursor.h"
|
||||
|
||||
#define NDB_PACKED_STR 0x1
|
||||
#define NDB_PACKED_ID 0x2
|
||||
|
||||
#define NDB_FLAG_NOMIGRATE (1 << 0)
|
||||
#define NDB_FLAG_SKIP_NOTE_VERIFY (1 << 1)
|
||||
|
||||
//#define DEBUG 1
|
||||
|
||||
#ifdef DEBUG
|
||||
#define ndb_debug(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define ndb_debug(...) (void)0
|
||||
#endif
|
||||
|
||||
struct ndb_json_parser;
|
||||
struct ndb;
|
||||
struct ndb_note;
|
||||
struct ndb_tag;
|
||||
struct ndb_tags;
|
||||
struct ndb_lmdb;
|
||||
union ndb_packed_str;
|
||||
|
||||
// sorry, swift needs help with forward declared pointers like this
|
||||
struct ndb_t {
|
||||
struct ndb *ndb;
|
||||
};
|
||||
|
||||
struct ndb_str {
|
||||
unsigned char flag;
|
||||
union {
|
||||
const char *str;
|
||||
unsigned char *id;
|
||||
};
|
||||
};
|
||||
|
||||
struct ndb_keypair {
|
||||
unsigned char pubkey[32];
|
||||
unsigned char secret[32];
|
||||
|
||||
// this corresponds to secp256k1's keypair type. it's guaranteed to
|
||||
// be 96 bytes according to their docs. I don't want to depend on
|
||||
// the secp256k1 header here so we just use raw bytes.
|
||||
unsigned char pair[96];
|
||||
};
|
||||
|
||||
// function pointer for controlling what to do after we parse an id
|
||||
typedef enum ndb_idres (*ndb_id_fn)(void *, const char *);
|
||||
|
||||
// id callback + closure data
|
||||
struct ndb_id_cb {
|
||||
ndb_id_fn fn;
|
||||
void *data;
|
||||
};
|
||||
|
||||
// required to keep a read
|
||||
struct ndb_txn {
|
||||
struct ndb_lmdb *lmdb;
|
||||
void *mdb_txn;
|
||||
};
|
||||
|
||||
struct ndb_event {
|
||||
struct ndb_note *note;
|
||||
};
|
||||
|
||||
struct ndb_command_result {
|
||||
int ok;
|
||||
const char *msg;
|
||||
int msglen;
|
||||
};
|
||||
|
||||
// From-client event types
|
||||
enum fce_type {
|
||||
NDB_FCE_EVENT = 0x1
|
||||
};
|
||||
|
||||
// To-client event types
|
||||
enum tce_type {
|
||||
NDB_TCE_EVENT = 0x1,
|
||||
NDB_TCE_OK = 0x2,
|
||||
NDB_TCE_NOTICE = 0x3,
|
||||
NDB_TCE_EOSE = 0x4,
|
||||
};
|
||||
|
||||
enum ndb_ingest_filter_action {
|
||||
NDB_INGEST_REJECT,
|
||||
NDB_INGEST_ACCEPT,
|
||||
NDB_INGEST_SKIP_VALIDATION
|
||||
};
|
||||
|
||||
struct ndb_search_key
|
||||
{
|
||||
char search[24];
|
||||
unsigned char id[32];
|
||||
uint64_t timestamp;
|
||||
};
|
||||
|
||||
struct ndb_search {
|
||||
struct ndb_search_key *key;
|
||||
uint64_t profile_key;
|
||||
void *cursor; // MDB_cursor *
|
||||
};
|
||||
|
||||
// From-client event
|
||||
struct ndb_fce {
|
||||
enum fce_type evtype;
|
||||
union {
|
||||
struct ndb_event event;
|
||||
};
|
||||
};
|
||||
|
||||
// To-client event
|
||||
struct ndb_tce {
|
||||
enum tce_type evtype;
|
||||
const char *subid;
|
||||
int subid_len;
|
||||
|
||||
union {
|
||||
struct ndb_event event;
|
||||
struct ndb_command_result command_result;
|
||||
};
|
||||
};
|
||||
|
||||
typedef enum ndb_ingest_filter_action (*ndb_ingest_filter_fn)(void *, struct ndb_note *);
|
||||
|
||||
enum ndb_filter_fieldtype {
|
||||
NDB_FILTER_IDS = 1,
|
||||
NDB_FILTER_AUTHORS = 2,
|
||||
NDB_FILTER_KINDS = 3,
|
||||
NDB_FILTER_GENERIC = 4,
|
||||
NDB_FILTER_SINCE = 5,
|
||||
NDB_FILTER_UNTIL = 6,
|
||||
NDB_FILTER_LIMIT = 7,
|
||||
};
|
||||
#define NDB_NUM_FILTERS 7
|
||||
|
||||
// when matching generic tags, we need to know if we're dealing with
|
||||
// a pointer to a 32-byte ID or a null terminated string
|
||||
enum ndb_generic_element_type {
|
||||
NDB_ELEMENT_UNKNOWN = 0,
|
||||
NDB_ELEMENT_STRING = 1,
|
||||
NDB_ELEMENT_ID = 2,
|
||||
};
|
||||
|
||||
enum ndb_search_order {
|
||||
NDB_ORDER_DESCENDING,
|
||||
NDB_ORDER_ASCENDING,
|
||||
};
|
||||
|
||||
enum ndb_dbs {
|
||||
NDB_DB_NOTE,
|
||||
NDB_DB_META,
|
||||
NDB_DB_PROFILE,
|
||||
NDB_DB_NOTE_ID,
|
||||
NDB_DB_PROFILE_PK, // profile pk index
|
||||
NDB_DB_NDB_META,
|
||||
NDB_DB_PROFILE_SEARCH,
|
||||
NDB_DB_PROFILE_LAST_FETCH,
|
||||
NDB_DB_NOTE_KIND, // note kind index
|
||||
NDB_DB_NOTE_TEXT, // note fulltext index
|
||||
NDB_DBS,
|
||||
};
|
||||
|
||||
// common kinds. we collect stats on these in ndb_stat. mainly because I don't
|
||||
// want to deal with including a hashtable to the project.
|
||||
enum ndb_common_kind {
|
||||
NDB_CKIND_PROFILE,
|
||||
NDB_CKIND_TEXT,
|
||||
NDB_CKIND_CONTACTS,
|
||||
NDB_CKIND_DM,
|
||||
NDB_CKIND_DELETE,
|
||||
NDB_CKIND_REPOST,
|
||||
NDB_CKIND_REACTION,
|
||||
NDB_CKIND_ZAP,
|
||||
NDB_CKIND_ZAP_REQUEST,
|
||||
NDB_CKIND_NWC_REQUEST,
|
||||
NDB_CKIND_NWC_RESPONSE,
|
||||
NDB_CKIND_HTTP_AUTH,
|
||||
NDB_CKIND_LIST,
|
||||
NDB_CKIND_LONGFORM,
|
||||
NDB_CKIND_STATUS,
|
||||
NDB_CKIND_COUNT, // should always be last
|
||||
};
|
||||
|
||||
struct ndb_builder {
|
||||
struct cursor mem;
|
||||
struct cursor note_cur;
|
||||
struct cursor strings;
|
||||
struct cursor str_indices;
|
||||
struct ndb_note *note;
|
||||
struct ndb_tag *current_tag;
|
||||
};
|
||||
|
||||
struct ndb_iterator {
|
||||
struct ndb_note *note;
|
||||
struct ndb_tag *tag;
|
||||
|
||||
// current outer index
|
||||
int index;
|
||||
};
|
||||
|
||||
union ndb_filter_element {
|
||||
const char *string;
|
||||
const unsigned char *id;
|
||||
uint64_t integer;
|
||||
};
|
||||
|
||||
struct ndb_filter_field {
|
||||
enum ndb_filter_fieldtype type;
|
||||
enum ndb_generic_element_type elem_type;
|
||||
char generic; // for generic queries like #t
|
||||
};
|
||||
|
||||
struct ndb_filter_elements {
|
||||
struct ndb_filter_field field;
|
||||
int count;
|
||||
union ndb_filter_element elements[0];
|
||||
};
|
||||
|
||||
struct ndb_filter {
|
||||
struct cursor elem_buf;
|
||||
struct cursor data_buf;
|
||||
int num_elements;
|
||||
struct ndb_filter_elements *current;
|
||||
struct ndb_filter_elements *elements[NDB_NUM_FILTERS];
|
||||
};
|
||||
|
||||
struct ndb_config {
|
||||
int flags;
|
||||
int ingester_threads;
|
||||
size_t mapsize;
|
||||
void *filter_context;
|
||||
ndb_ingest_filter_fn ingest_filter;
|
||||
};
|
||||
|
||||
struct ndb_text_search_config {
|
||||
enum ndb_search_order order;
|
||||
int limit;
|
||||
};
|
||||
|
||||
struct ndb_stat_counts {
|
||||
size_t key_size;
|
||||
size_t value_size;
|
||||
size_t count;
|
||||
};
|
||||
|
||||
struct ndb_stat {
|
||||
struct ndb_stat_counts dbs[NDB_DBS];
|
||||
struct ndb_stat_counts common_kinds[NDB_CKIND_COUNT];
|
||||
struct ndb_stat_counts other_kinds;
|
||||
};
|
||||
|
||||
#define MAX_TEXT_SEARCH_RESULTS 128
|
||||
#define MAX_TEXT_SEARCH_WORDS 8
|
||||
|
||||
// unpacked form of the actual lmdb fulltext search key
|
||||
// see `ndb_make_text_search_key` for how the packed version is constructed
|
||||
struct ndb_text_search_key
|
||||
{
|
||||
int str_len;
|
||||
const char *str;
|
||||
uint64_t timestamp;
|
||||
uint64_t note_id;
|
||||
int word_index;
|
||||
};
|
||||
|
||||
struct ndb_text_search_result {
|
||||
struct ndb_text_search_key key;
|
||||
int prefix_chars;
|
||||
};
|
||||
|
||||
struct ndb_text_search_results {
|
||||
struct ndb_text_search_result results[MAX_TEXT_SEARCH_RESULTS];
|
||||
int num_results;
|
||||
};
|
||||
|
||||
|
||||
// CONFIG
|
||||
void ndb_default_config(struct ndb_config *);
|
||||
void ndb_config_set_ingest_threads(struct ndb_config *config, int threads);
|
||||
void ndb_config_set_flags(struct ndb_config *config, int flags);
|
||||
void ndb_config_set_mapsize(struct ndb_config *config, size_t mapsize);
|
||||
void ndb_config_set_ingest_filter(struct ndb_config *config, ndb_ingest_filter_fn fn, void *);
|
||||
|
||||
// HELPERS
|
||||
int ndb_calculate_id(struct ndb_note *note, unsigned char *buf, int buflen);
|
||||
int ndb_sign_id(struct ndb_keypair *keypair, unsigned char id[32], unsigned char sig[64]);
|
||||
int ndb_create_keypair(struct ndb_keypair *key);
|
||||
int ndb_decode_key(const char *secstr, struct ndb_keypair *keypair);
|
||||
int ndb_note_verify(void *secp_ctx, unsigned char pubkey[32], unsigned char id[32], unsigned char signature[64]);
|
||||
|
||||
// NDB
|
||||
int ndb_init(struct ndb **ndb, const char *dbdir, const struct ndb_config *);
|
||||
int ndb_db_version(struct ndb *ndb);
|
||||
int ndb_process_event(struct ndb *, const char *json, int len);
|
||||
int ndb_process_events(struct ndb *, const char *ldjson, size_t len);
|
||||
int ndb_process_events_stream(struct ndb *, FILE* fp);
|
||||
int ndb_process_client_event(struct ndb *, const char *json, int len);
|
||||
int ndb_process_client_events(struct ndb *, const char *json, size_t len);
|
||||
int ndb_begin_query(struct ndb *, struct ndb_txn *);
|
||||
int ndb_search_profile(struct ndb_txn *txn, struct ndb_search *search, const char *query);
|
||||
int ndb_search_profile_next(struct ndb_search *search);
|
||||
void ndb_search_profile_end(struct ndb_search *search);
|
||||
int ndb_end_query(struct ndb_txn *);
|
||||
int ndb_write_last_profile_fetch(struct ndb *ndb, const unsigned char *pubkey, uint64_t fetched_at);
|
||||
uint64_t ndb_read_last_profile_fetch(struct ndb_txn *txn, const unsigned char *pubkey);
|
||||
void *ndb_get_profile_by_pubkey(struct ndb_txn *txn, const unsigned char *pubkey, size_t *len, uint64_t *primkey);
|
||||
void *ndb_get_profile_by_key(struct ndb_txn *txn, uint64_t key, size_t *len);
|
||||
uint64_t ndb_get_notekey_by_id(struct ndb_txn *txn, const unsigned char *id);
|
||||
uint64_t ndb_get_profilekey_by_pubkey(struct ndb_txn *txn, const unsigned char *id);
|
||||
struct ndb_note *ndb_get_note_by_id(struct ndb_txn *txn, const unsigned char *id, size_t *len, uint64_t *primkey);
|
||||
struct ndb_note *ndb_get_note_by_key(struct ndb_txn *txn, uint64_t key, size_t *len);
|
||||
void *ndb_get_note_meta(struct ndb_txn *txn, const unsigned char *id, size_t *len);
|
||||
void ndb_destroy(struct ndb *);
|
||||
|
||||
// BUILDER
|
||||
int ndb_parse_json_note(struct ndb_json_parser *, struct ndb_note **);
|
||||
int ndb_client_event_from_json(const char *json, int len, struct ndb_fce *fce, unsigned char *buf, int bufsize, struct ndb_id_cb *cb);
|
||||
int ndb_ws_event_from_json(const char *json, int len, struct ndb_tce *tce, unsigned char *buf, int bufsize, struct ndb_id_cb *);
|
||||
int ndb_note_from_json(const char *json, int len, struct ndb_note **, unsigned char *buf, int buflen);
|
||||
int ndb_builder_init(struct ndb_builder *builder, unsigned char *buf, size_t bufsize);
|
||||
int ndb_builder_finalize(struct ndb_builder *builder, struct ndb_note **note, struct ndb_keypair *privkey);
|
||||
int ndb_builder_set_content(struct ndb_builder *builder, const char *content, int len);
|
||||
void ndb_builder_set_created_at(struct ndb_builder *builder, uint64_t created_at);
|
||||
void ndb_builder_set_sig(struct ndb_builder *builder, unsigned char *sig);
|
||||
void ndb_builder_set_pubkey(struct ndb_builder *builder, unsigned char *pubkey);
|
||||
void ndb_builder_set_id(struct ndb_builder *builder, unsigned char *id);
|
||||
void ndb_builder_set_kind(struct ndb_builder *builder, uint32_t kind);
|
||||
int ndb_builder_new_tag(struct ndb_builder *builder);
|
||||
int ndb_builder_push_tag_str(struct ndb_builder *builder, const char *str, int len);
|
||||
|
||||
// FILTERS
|
||||
int ndb_filter_init(struct ndb_filter *);
|
||||
int ndb_filter_add_id_element(struct ndb_filter *, const unsigned char *id);
|
||||
int ndb_filter_add_int_element(struct ndb_filter *, uint64_t integer);
|
||||
int ndb_filter_add_str_element(struct ndb_filter *, const char *str);
|
||||
int ndb_filter_start_field(struct ndb_filter *, enum ndb_filter_fieldtype);
|
||||
int ndb_filter_start_generic_field(struct ndb_filter *, char tag);
|
||||
int ndb_filter_matches(struct ndb_filter *, struct ndb_note *);
|
||||
void ndb_filter_reset(struct ndb_filter *);
|
||||
void ndb_filter_end_field(struct ndb_filter *);
|
||||
void ndb_filter_free(struct ndb_filter *);
|
||||
|
||||
// FULLTEXT SEARCH
|
||||
int ndb_text_search(struct ndb_txn *txn, const char *query, struct ndb_text_search_results *, struct ndb_text_search_config *);
|
||||
void ndb_default_text_search_config(struct ndb_text_search_config *);
|
||||
void ndb_text_search_config_set_order(struct ndb_text_search_config *, enum ndb_search_order);
|
||||
void ndb_text_search_config_set_limit(struct ndb_text_search_config *, int limit);
|
||||
|
||||
// STATS
|
||||
int ndb_stat(struct ndb *ndb, struct ndb_stat *stat);
|
||||
void ndb_stat_counts_init(struct ndb_stat_counts *counts);
|
||||
|
||||
// NOTE
|
||||
const char *ndb_note_content(struct ndb_note *note);
|
||||
struct ndb_str ndb_note_str(struct ndb_note *note, union ndb_packed_str *pstr);
|
||||
uint32_t ndb_note_content_length(struct ndb_note *note);
|
||||
uint32_t ndb_note_created_at(struct ndb_note *note);
|
||||
uint32_t ndb_note_kind(struct ndb_note *note);
|
||||
unsigned char *ndb_note_id(struct ndb_note *note);
|
||||
unsigned char *ndb_note_pubkey(struct ndb_note *note);
|
||||
unsigned char *ndb_note_sig(struct ndb_note *note);
|
||||
void _ndb_note_set_kind(struct ndb_note *note, uint32_t kind);
|
||||
struct ndb_tags *ndb_note_tags(struct ndb_note *note);
|
||||
|
||||
// TAGS
|
||||
void ndb_tags_iterate_start(struct ndb_note *note, struct ndb_iterator *iter);
|
||||
uint16_t ndb_tags_count(struct ndb_tags *);
|
||||
uint16_t ndb_tag_count(struct ndb_tag *);
|
||||
|
||||
// ITER
|
||||
int ndb_tags_iterate_next(struct ndb_iterator *iter);
|
||||
struct ndb_str ndb_iter_tag_str(struct ndb_iterator *iter, int ind);
|
||||
struct ndb_str ndb_tag_str(struct ndb_note *note, struct ndb_tag *tag, int ind);
|
||||
|
||||
// NAMES
|
||||
const char *ndb_db_name(enum ndb_dbs db);
|
||||
const char *ndb_kind_name(enum ndb_common_kind ck);
|
||||
enum ndb_common_kind ndb_kind_to_common_kind(int kind);
|
||||
|
||||
#endif
|
||||
36
nostrdb/src/print_util.h
Normal file
36
nostrdb/src/print_util.h
Normal file
@@ -0,0 +1,36 @@
|
||||
|
||||
static void ndb_print_text_search_key(struct ndb_text_search_key *key)
|
||||
{
|
||||
printf("K<'%.*s' %d %" PRIu64 " note_id:%" PRIu64 ">", key->str_len, key->str,
|
||||
key->word_index,
|
||||
key->timestamp,
|
||||
key->note_id);
|
||||
}
|
||||
|
||||
static void print_hex(unsigned char* data, size_t size) {
|
||||
size_t i;
|
||||
for (i = 0; i < size; i++) {
|
||||
printf("%02x", data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void ndb_print_text_search_result(struct ndb_txn *txn,
|
||||
struct ndb_text_search_result *r)
|
||||
{
|
||||
size_t len;
|
||||
struct ndb_note *note;
|
||||
|
||||
ndb_print_text_search_key(&r->key);
|
||||
|
||||
if (!(note = ndb_get_note_by_key(txn, r->key.note_id, &len))) {
|
||||
printf(": note not found");
|
||||
return;
|
||||
}
|
||||
|
||||
printf(" ");
|
||||
print_hex(ndb_note_id(note), 32);
|
||||
|
||||
printf("\n%s\n\n---\n", ndb_note_content(note));
|
||||
}
|
||||
|
||||
235
nostrdb/src/protected_queue.h
Normal file
235
nostrdb/src/protected_queue.h
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* This header file provides a thread-safe queue implementation for generic
|
||||
* data elements. It uses POSIX threads (pthreads) to ensure thread safety.
|
||||
* The queue allows for pushing and popping elements, with the ability to
|
||||
* block or non-block on pop operations. Users are responsible for providing
|
||||
* memory for the queue buffer and ensuring its correct lifespan.
|
||||
*
|
||||
* Author: William Casarin
|
||||
* Inspired-by: https://github.com/hoytech/hoytech-cpp/blob/master/hoytech/protected_queue.h
|
||||
*/
|
||||
|
||||
#ifndef PROT_QUEUE_H
|
||||
#define PROT_QUEUE_H
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "cursor.h"
|
||||
#include "util.h"
|
||||
|
||||
#define BUFFER_SIZE 100
|
||||
|
||||
/*
|
||||
* The prot_queue structure represents a thread-safe queue that can hold
|
||||
* generic data elements.
|
||||
*/
|
||||
struct prot_queue {
|
||||
unsigned char *buf;
|
||||
size_t buflen;
|
||||
|
||||
int head;
|
||||
int tail;
|
||||
int count;
|
||||
int elem_size;
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the queue.
|
||||
* Params:
|
||||
* q - Pointer to the queue.
|
||||
* buf - Buffer for holding data elements.
|
||||
* buflen - Length of the buffer.
|
||||
* elem_size - Size of each data element.
|
||||
* Returns 1 if successful, 0 otherwise.
|
||||
*/
|
||||
static inline int prot_queue_init(struct prot_queue* q, void* buf,
|
||||
size_t buflen, int elem_size)
|
||||
{
|
||||
// buffer elements must fit nicely in the buffer
|
||||
if (buflen == 0 || buflen % elem_size != 0)
|
||||
return 0;
|
||||
|
||||
q->head = 0;
|
||||
q->tail = 0;
|
||||
q->count = 0;
|
||||
q->buf = buf;
|
||||
q->buflen = buflen;
|
||||
q->elem_size = elem_size;
|
||||
|
||||
pthread_mutex_init(&q->mutex, NULL);
|
||||
pthread_cond_init(&q->cond, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the capacity of the queue.
|
||||
* q - Pointer to the queue.
|
||||
*/
|
||||
static inline size_t prot_queue_capacity(struct prot_queue *q) {
|
||||
return q->buflen / q->elem_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Push an element onto the queue.
|
||||
* Params:
|
||||
* q - Pointer to the queue.
|
||||
* data - Pointer to the data element to be pushed.
|
||||
*
|
||||
* Returns 1 if successful, 0 if the queue is full.
|
||||
*/
|
||||
static int prot_queue_push(struct prot_queue* q, void *data)
|
||||
{
|
||||
int cap;
|
||||
|
||||
pthread_mutex_lock(&q->mutex);
|
||||
|
||||
cap = prot_queue_capacity(q);
|
||||
if (q->count == cap) {
|
||||
// only signal if the push was sucessful
|
||||
pthread_mutex_unlock(&q->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&q->buf[q->tail * q->elem_size], data, q->elem_size);
|
||||
q->tail = (q->tail + 1) % cap;
|
||||
q->count++;
|
||||
|
||||
pthread_cond_signal(&q->cond);
|
||||
pthread_mutex_unlock(&q->mutex);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Push multiple elements onto the queue.
|
||||
* Params:
|
||||
* q - Pointer to the queue.
|
||||
* data - Pointer to the data elements to be pushed.
|
||||
* count - Number of elements to push.
|
||||
*
|
||||
* Returns the number of elements successfully pushed, 0 if the queue is full or if there is not enough contiguous space.
|
||||
*/
|
||||
static int prot_queue_push_all(struct prot_queue* q, void *data, int count)
|
||||
{
|
||||
int cap;
|
||||
int first_copy_count, second_copy_count;
|
||||
|
||||
pthread_mutex_lock(&q->mutex);
|
||||
|
||||
cap = prot_queue_capacity(q);
|
||||
if (q->count + count > cap) {
|
||||
pthread_mutex_unlock(&q->mutex);
|
||||
return 0; // Return failure if the queue is full
|
||||
}
|
||||
|
||||
first_copy_count = min(count, cap - q->tail); // Elements until the end of the buffer
|
||||
second_copy_count = count - first_copy_count; // Remaining elements if wrap around
|
||||
|
||||
memcpy(&q->buf[q->tail * q->elem_size], data, first_copy_count * q->elem_size);
|
||||
q->tail = (q->tail + first_copy_count) % cap;
|
||||
|
||||
if (second_copy_count > 0) {
|
||||
// If there is a wrap around, copy the remaining elements
|
||||
memcpy(&q->buf[q->tail * q->elem_size], (char *)data + first_copy_count * q->elem_size, second_copy_count * q->elem_size);
|
||||
q->tail = (q->tail + second_copy_count) % cap;
|
||||
}
|
||||
|
||||
q->count += count;
|
||||
|
||||
pthread_cond_signal(&q->cond); // Signal a waiting thread
|
||||
pthread_mutex_unlock(&q->mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to pop an element from the queue without blocking.
|
||||
* Params:
|
||||
* q - Pointer to the queue.
|
||||
* data - Pointer to where the popped data will be stored.
|
||||
* Returns 1 if successful, 0 if the queue is empty.
|
||||
*/
|
||||
static inline int prot_queue_try_pop(struct prot_queue *q, void *data) {
|
||||
pthread_mutex_lock(&q->mutex);
|
||||
|
||||
if (q->count == 0) {
|
||||
pthread_mutex_unlock(&q->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(data, &q->buf[q->head * q->elem_size], q->elem_size);
|
||||
q->head = (q->head + 1) % prot_queue_capacity(q);
|
||||
q->count--;
|
||||
|
||||
pthread_mutex_unlock(&q->mutex);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait until we have elements, and then pop multiple elements from the queue
|
||||
* up to the specified maximum.
|
||||
*
|
||||
* Params:
|
||||
* q - Pointer to the queue.
|
||||
* buffer - Pointer to the buffer where popped data will be stored.
|
||||
* max_items - Maximum number of items to pop from the queue.
|
||||
* Returns the actual number of items popped.
|
||||
*/
|
||||
static int prot_queue_pop_all(struct prot_queue *q, void *dest, int max_items) {
|
||||
pthread_mutex_lock(&q->mutex);
|
||||
|
||||
// Wait until there's at least one item to pop
|
||||
while (q->count == 0) {
|
||||
pthread_cond_wait(&q->cond, &q->mutex);
|
||||
}
|
||||
|
||||
int items_until_end = (q->buflen - q->head * q->elem_size) / q->elem_size;
|
||||
int items_to_pop = min(q->count, max_items);
|
||||
items_to_pop = min(items_to_pop, items_until_end);
|
||||
|
||||
memcpy(dest, &q->buf[q->head * q->elem_size], items_to_pop * q->elem_size);
|
||||
q->head = (q->head + items_to_pop) % prot_queue_capacity(q);
|
||||
q->count -= items_to_pop;
|
||||
|
||||
pthread_mutex_unlock(&q->mutex);
|
||||
|
||||
return items_to_pop;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pop an element from the queue. Blocks if the queue is empty.
|
||||
* Params:
|
||||
* q - Pointer to the queue.
|
||||
* data - Pointer to where the popped data will be stored.
|
||||
*/
|
||||
static inline void prot_queue_pop(struct prot_queue *q, void *data) {
|
||||
pthread_mutex_lock(&q->mutex);
|
||||
|
||||
while (q->count == 0)
|
||||
pthread_cond_wait(&q->cond, &q->mutex);
|
||||
|
||||
memcpy(data, &q->buf[q->head * q->elem_size], q->elem_size);
|
||||
q->head = (q->head + 1) % prot_queue_capacity(q);
|
||||
q->count--;
|
||||
|
||||
pthread_mutex_unlock(&q->mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy the queue. Releases resources associated with the queue.
|
||||
* Params:
|
||||
* q - Pointer to the queue.
|
||||
*/
|
||||
static inline void prot_queue_destroy(struct prot_queue* q) {
|
||||
pthread_mutex_destroy(&q->mutex);
|
||||
pthread_cond_destroy(&q->cond);
|
||||
}
|
||||
|
||||
#endif // PROT_QUEUE_H
|
||||
65
nostrdb/src/random.h
Normal file
65
nostrdb/src/random.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*************************************************************************
|
||||
* Copyright (c) 2020-2021 Elichai Turkel *
|
||||
* Distributed under the CC0 software license, see the accompanying file *
|
||||
* EXAMPLES_COPYING or https://creativecommons.org/publicdomain/zero/1.0 *
|
||||
*************************************************************************/
|
||||
|
||||
/*
|
||||
* This file is an attempt at collecting best practice methods for obtaining randomness with different operating systems.
|
||||
* It may be out-of-date. Consult the documentation of the operating system before considering to use the methods below.
|
||||
*
|
||||
* Platform randomness sources:
|
||||
* Linux -> `getrandom(2)`(`sys/random.h`), if not available `/dev/urandom` should be used. http://man7.org/linux/man-pages/man2/getrandom.2.html, https://linux.die.net/man/4/urandom
|
||||
* macOS -> `getentropy(2)`(`sys/random.h`), if not available `/dev/urandom` should be used. https://www.unix.com/man-page/mojave/2/getentropy, https://opensource.apple.com/source/xnu/xnu-517.12.7/bsd/man/man4/random.4.auto.html
|
||||
* FreeBSD -> `getrandom(2)`(`sys/random.h`), if not available `kern.arandom` should be used. https://www.freebsd.org/cgi/man.cgi?query=getrandom, https://www.freebsd.org/cgi/man.cgi?query=random&sektion=4
|
||||
* OpenBSD -> `getentropy(2)`(`unistd.h`), if not available `/dev/urandom` should be used. https://man.openbsd.org/getentropy, https://man.openbsd.org/urandom
|
||||
* Windows -> `BCryptGenRandom`(`bcrypt.h`). https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
|
||||
*/
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#include <ntstatus.h>
|
||||
#include <bcrypt.h>
|
||||
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)
|
||||
#include <sys/random.h>
|
||||
#elif defined(__OpenBSD__)
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#error "Couldn't identify the OS"
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
/* Returns 1 on success, and 0 on failure. */
|
||||
static int fill_random(unsigned char* data, size_t size) {
|
||||
#if defined(_WIN32)
|
||||
NTSTATUS res = BCryptGenRandom(NULL, data, size, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
|
||||
if (res != STATUS_SUCCESS || size > ULONG_MAX) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
#elif defined(__linux__) || defined(__FreeBSD__)
|
||||
/* If `getrandom(2)` is not available you should fallback to /dev/urandom */
|
||||
ssize_t res = getrandom(data, size, 0);
|
||||
if (res < 0 || (size_t)res != size ) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
#elif defined(__APPLE__) || defined(__OpenBSD__)
|
||||
/* If `getentropy(2)` is not available you should fallback to either
|
||||
* `SecRandomCopyBytes` or /dev/urandom */
|
||||
int res = getentropy(data, size);
|
||||
if (res == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
302
nostrdb/src/sha256.c
Normal file
302
nostrdb/src/sha256.c
Normal file
@@ -0,0 +1,302 @@
|
||||
/* 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 "endian.h"
|
||||
#include "compiler.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)
|
||||
{
|
||||
#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 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));
|
||||
}
|
||||
|
||||
|
||||
155
nostrdb/src/sha256.h
Normal file
155
nostrdb/src/sha256.h
Normal file
@@ -0,0 +1,155 @@
|
||||
|
||||
#ifndef CCAN_CRYPTO_SHA256_H
|
||||
#define CCAN_CRYPTO_SHA256_H
|
||||
|
||||
|
||||
/** Output length for `wally_sha256` */
|
||||
#define SHA256_LEN 32
|
||||
|
||||
|
||||
/* 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 @p
|
||||
*
|
||||
* 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 @p
|
||||
*
|
||||
* 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 */
|
||||
103
nostrdb/src/threadpool.h
Normal file
103
nostrdb/src/threadpool.h
Normal file
@@ -0,0 +1,103 @@
|
||||
|
||||
#ifndef THREADPOOL_H
|
||||
#define THREADPOOL_H
|
||||
|
||||
#include "protected_queue.h"
|
||||
|
||||
struct thread
|
||||
{
|
||||
pthread_t thread_id;
|
||||
struct prot_queue inbox;
|
||||
void *qmem;
|
||||
void *ctx;
|
||||
};
|
||||
|
||||
struct threadpool
|
||||
{
|
||||
int num_threads;
|
||||
struct thread *pool;
|
||||
int next_thread;
|
||||
void *quit_msg;
|
||||
};
|
||||
|
||||
static int threadpool_init(struct threadpool *tp, int num_threads,
|
||||
int q_elem_size, int q_num_elems,
|
||||
void *quit_msg, void *ctx, void* (*thread_fn)(void*))
|
||||
{
|
||||
int i;
|
||||
struct thread *t;
|
||||
|
||||
if (num_threads <= 0)
|
||||
return 0;
|
||||
|
||||
tp->num_threads = num_threads;
|
||||
tp->pool = malloc(sizeof(*tp->pool) * num_threads);
|
||||
tp->quit_msg = quit_msg;
|
||||
tp->next_thread = -1;
|
||||
|
||||
if (tp->pool == NULL) {
|
||||
fprintf(stderr, "threadpool_init: couldn't allocate memory for pool");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_threads; i++) {
|
||||
t = &tp->pool[i];
|
||||
t->qmem = malloc(q_elem_size * q_num_elems);
|
||||
t->ctx = ctx;
|
||||
|
||||
if (t->qmem == NULL) {
|
||||
fprintf(stderr, "threadpool_init: couldn't allocate memory for queue");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!prot_queue_init(&t->inbox, t->qmem, q_elem_size * q_num_elems, q_elem_size)) {
|
||||
fprintf(stderr, "threadpool_init: couldn't init queue. buffer alignment is wrong.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pthread_create(&t->thread_id, NULL, thread_fn, t) != 0) {
|
||||
fprintf(stderr, "threadpool_init: failed to create thread\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline struct thread *threadpool_next_thread(struct threadpool *tp)
|
||||
{
|
||||
tp->next_thread = (tp->next_thread + 1) % tp->num_threads;
|
||||
return &tp->pool[tp->next_thread];
|
||||
}
|
||||
|
||||
static inline int threadpool_dispatch(struct threadpool *tp, void *msg)
|
||||
{
|
||||
struct thread *t = threadpool_next_thread(tp);
|
||||
return prot_queue_push(&t->inbox, msg);
|
||||
}
|
||||
|
||||
static inline int threadpool_dispatch_all(struct threadpool *tp, void *msgs,
|
||||
int num_msgs)
|
||||
{
|
||||
struct thread *t = threadpool_next_thread(tp);
|
||||
return prot_queue_push_all(&t->inbox, msgs, num_msgs);
|
||||
}
|
||||
|
||||
static inline void threadpool_destroy(struct threadpool *tp)
|
||||
{
|
||||
struct thread *t;
|
||||
|
||||
for (int i = 0; i < tp->num_threads; i++) {
|
||||
t = &tp->pool[i];
|
||||
if (!prot_queue_push(&t->inbox, tp->quit_msg)) {
|
||||
pthread_exit(&t->thread_id);
|
||||
} else {
|
||||
pthread_join(t->thread_id, NULL);
|
||||
}
|
||||
prot_queue_destroy(&t->inbox);
|
||||
free(t->qmem);
|
||||
}
|
||||
free(tp->pool);
|
||||
}
|
||||
|
||||
#endif // THREADPOOL_H
|
||||
14
nostrdb/src/typedefs.h
Normal file
14
nostrdb/src/typedefs.h
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
#ifndef PROTOVERSE_TYPEDEFS_H
|
||||
#define PROTOVERSE_TYPEDEFS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned short u16;
|
||||
typedef uint64_t u64;
|
||||
typedef int64_t s64;
|
||||
|
||||
|
||||
#endif /* PROTOVERSE_TYPEDEFS_H */
|
||||
33
nostrdb/src/util.h
Normal file
33
nostrdb/src/util.h
Normal file
@@ -0,0 +1,33 @@
|
||||
|
||||
#ifndef NDB_UTIL_H
|
||||
#define NDB_UTIL_H
|
||||
|
||||
static inline int min(int a, int b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
static inline int max(int a, int b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
static inline void* memdup(const void* src, size_t size) {
|
||||
void* dest = malloc(size);
|
||||
if (dest == NULL) {
|
||||
return NULL; // Memory allocation failed
|
||||
}
|
||||
memcpy(dest, src, size);
|
||||
return dest;
|
||||
}
|
||||
|
||||
static inline char *strdupn(const char *src, size_t size) {
|
||||
char* dest = malloc(size+1);
|
||||
if (dest == NULL) {
|
||||
return NULL; // Memory allocation failed
|
||||
}
|
||||
memcpy(dest, src, size);
|
||||
dest[size] = '\0';
|
||||
return dest;
|
||||
}
|
||||
|
||||
#endif // NDB_UTIL_H
|
||||
|
||||
Reference in New Issue
Block a user