nostrdb/blocks: add note block iterator
This adds an api that walks along and pulls compact note block data out of nostrdb. Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
committed by
Daniel D’Aquino
parent
6f9bd6c4f4
commit
034f2cc02f
184
nostrdb/src/block.c
Normal file
184
nostrdb/src/block.c
Normal file
@@ -0,0 +1,184 @@
|
||||
|
||||
|
||||
#include "nostrdb.h"
|
||||
#include "block.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
struct ndb_block_iterator {
|
||||
const char *content;
|
||||
struct ndb_blocks *blocks;
|
||||
struct ndb_block block;
|
||||
struct cursor cur;
|
||||
};
|
||||
|
||||
int push_str_block(struct cursor *buf, const char *content, struct ndb_str_block *block) {
|
||||
return cursor_push_varint(buf, block->str - content) &&
|
||||
cursor_push_varint(buf, block->len);
|
||||
}
|
||||
|
||||
int pull_str_block(struct cursor *buf, const char *content, struct ndb_str_block *block) {
|
||||
uint32_t start;
|
||||
if (!cursor_pull_varint_u32(buf, &start))
|
||||
return 0;
|
||||
|
||||
block->str = content + start;
|
||||
|
||||
return cursor_pull_varint_u32(buf, &block->len);
|
||||
}
|
||||
|
||||
static int pull_nostr_bech32_type(struct cursor *cur, enum nostr_bech32_type *type)
|
||||
{
|
||||
uint64_t inttype;
|
||||
if (!cursor_pull_varint(cur, &inttype))
|
||||
return 0;
|
||||
|
||||
if (inttype > NOSTR_BECH32_KNOWN_TYPES)
|
||||
return 0;
|
||||
|
||||
*type = inttype;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int pull_bech32_mention(const char *content, struct cursor *cur, struct ndb_mention_bech32_block *block) {
|
||||
uint16_t size;
|
||||
unsigned char *start;
|
||||
enum nostr_bech32_type type;
|
||||
|
||||
start = cur->p;
|
||||
|
||||
if (!pull_str_block(cur, content, &block->str))
|
||||
return 0;
|
||||
|
||||
if (!cursor_pull_u16(cur, &size))
|
||||
return 0;
|
||||
|
||||
if (!pull_nostr_bech32_type(cur, &type))
|
||||
return 0;
|
||||
|
||||
if (!parse_nostr_bech32_buffer(cur, type, &block->bech32))
|
||||
return 0;
|
||||
|
||||
cur->p = start + size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pull_invoice(const char *content, struct cursor *cur,
|
||||
struct ndb_invoice_block *block)
|
||||
{
|
||||
if (!pull_str_block(cur, content, &block->invstr))
|
||||
return 0;
|
||||
|
||||
return ndb_decode_invoice(cur, &block->invoice);
|
||||
}
|
||||
|
||||
static int pull_block_type(struct cursor *cur, enum ndb_block_type *type)
|
||||
{
|
||||
uint32_t itype;
|
||||
*type = 0;
|
||||
if (!cursor_pull_varint_u32(cur, &itype))
|
||||
return 0;
|
||||
|
||||
if (itype <= 0 || itype > NDB_NUM_BLOCK_TYPES)
|
||||
return 0;
|
||||
|
||||
*type = itype;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pull_block(const char *content, struct cursor *cur, struct ndb_block *block)
|
||||
{
|
||||
unsigned char *start = cur->p;
|
||||
|
||||
if (!pull_block_type(cur, &block->type))
|
||||
return 0;
|
||||
|
||||
switch (block->type) {
|
||||
case BLOCK_HASHTAG:
|
||||
case BLOCK_TEXT:
|
||||
case BLOCK_URL:
|
||||
if (!pull_str_block(cur, content, &block->block.str))
|
||||
goto fail;
|
||||
break;
|
||||
|
||||
case BLOCK_MENTION_INDEX:
|
||||
if (!cursor_pull_varint_u32(cur, &block->block.mention_index))
|
||||
goto fail;
|
||||
break;
|
||||
|
||||
case BLOCK_MENTION_BECH32:
|
||||
if (!pull_bech32_mention(content, cur, &block->block.mention_bech32))
|
||||
goto fail;
|
||||
break;
|
||||
|
||||
case BLOCK_INVOICE:
|
||||
// we only push invoice strs here
|
||||
if (!pull_invoice(content, cur, &block->block.invoice))
|
||||
goto fail;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
fail:
|
||||
cur->p = start;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
enum ndb_block_type ndb_get_block_type(struct ndb_block *block) {
|
||||
return block->type;
|
||||
}
|
||||
|
||||
// BLOCK ITERATORS
|
||||
struct ndb_block_iterator *ndb_blocks_iterate_start(const char *content, struct ndb_blocks *blocks) {
|
||||
struct ndb_block_iterator *iter = malloc(sizeof(*iter));
|
||||
if (!iter)
|
||||
return NULL;
|
||||
|
||||
iter->blocks = blocks;
|
||||
iter->content = content;
|
||||
|
||||
make_cursor((unsigned char *)blocks->blocks,
|
||||
blocks->blocks + blocks->blocks_size, &iter->cur);
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
void ndb_blocks_iterate_free(struct ndb_block_iterator *iter)
|
||||
{
|
||||
if (iter)
|
||||
free(iter);
|
||||
}
|
||||
|
||||
struct ndb_block *ndb_blocks_iterate_next(struct ndb_block_iterator *iter)
|
||||
{
|
||||
while (iter->cur.p < iter->cur.end) {
|
||||
if (!pull_block(iter->content, &iter->cur, &iter->block))
|
||||
return NULL;
|
||||
else
|
||||
return &iter->block;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// STR BLOCKS
|
||||
struct ndb_str_block *ndb_block_str(struct ndb_block *block)
|
||||
{
|
||||
switch (block->type) {
|
||||
case BLOCK_HASHTAG:
|
||||
case BLOCK_TEXT:
|
||||
case BLOCK_URL:
|
||||
return &block->block.str;
|
||||
case BLOCK_MENTION_INDEX:
|
||||
return NULL;
|
||||
case BLOCK_MENTION_BECH32:
|
||||
return &block->block.mention_bech32.str;
|
||||
case BLOCK_INVOICE:
|
||||
return &block->block.invoice.invstr;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
//const char *ndb_str_block_ptr(struct ndb_str_block *);
|
||||
//uint32_t ndb_str_block_len(struct ndb_str_block *);
|
||||
Reference in New Issue
Block a user