nostrdb

an unfairly fast embedded nostr database backed by lmdb
git clone git://jb55.com/nostrdb
Log | Files | Refs | Submodules | README | LICENSE

block.c (4410B)


      1 
      2 
      3 #include "nostrdb.h"
      4 #include "block.h"
      5 #include <stdlib.h>
      6 
      7 int push_str_block(struct cursor *buf, const char *content, struct ndb_str_block *block) {
      8 	return cursor_push_varint(buf, block->str - content) &&
      9 	       cursor_push_varint(buf, block->len);
     10 }
     11 
     12 int pull_str_block(struct cursor *buf, const char *content, struct ndb_str_block *block) {
     13 	uint32_t start;
     14 	if (!cursor_pull_varint_u32(buf, &start))
     15 		return 0;
     16 
     17 	block->str = content + start;
     18 
     19 	return cursor_pull_varint_u32(buf, &block->len);
     20 }
     21 
     22 static int pull_nostr_bech32_type(struct cursor *cur, enum nostr_bech32_type *type)
     23 {
     24 	uint64_t inttype;
     25 	if (!cursor_pull_varint(cur, &inttype))
     26 		return 0;
     27 
     28 	if (inttype <= 0 || inttype > NOSTR_BECH32_KNOWN_TYPES)
     29 		return 0;
     30 
     31 	*type = inttype;
     32 	return 1;
     33 }
     34 
     35 
     36 static int pull_bech32_mention(const char *content, struct cursor *cur, struct ndb_mention_bech32_block *block) {
     37 	uint16_t size;
     38 	unsigned char *start;
     39 	struct cursor bech32;
     40 
     41 	if (!pull_str_block(cur, content, &block->str))
     42 		return 0;
     43 
     44 	if (!cursor_pull_u16(cur, &size))
     45 		return 0;
     46 
     47 	if (!pull_nostr_bech32_type(cur, &block->bech32.type))
     48 		return 0;
     49 
     50 	make_cursor(cur->p, cur->p + size, &bech32);
     51 
     52 	start = cur->p;
     53 
     54 	if (!parse_nostr_bech32_buffer(&bech32, block->bech32.type, &block->bech32))
     55 		return 0;
     56 
     57 	//assert(bech32.p == start + size);
     58 	cur->p = start + size;
     59 	return 1;
     60 }
     61 
     62 static int pull_invoice(const char *content, struct cursor *cur,
     63 			struct ndb_invoice_block *block)
     64 {
     65 	if (!pull_str_block(cur, content, &block->invstr))
     66 		return 0;
     67 
     68 	return ndb_decode_invoice(cur, &block->invoice);
     69 }
     70 
     71 static int pull_block_type(struct cursor *cur, enum ndb_block_type *type)
     72 {
     73 	uint32_t itype;
     74 	*type = 0;
     75 	if (!cursor_pull_varint_u32(cur, &itype))
     76 		return 0;
     77 
     78 	if (itype <= 0 || itype > NDB_NUM_BLOCK_TYPES)
     79 		return 0;
     80 
     81 	*type = itype;
     82 	return 1;
     83 }
     84 
     85 static int pull_block(const char *content, struct cursor *cur, struct ndb_block *block)
     86 {
     87 	unsigned char *start = cur->p;
     88 
     89 	if (!pull_block_type(cur, &block->type))
     90 		return 0;
     91 
     92 	switch (block->type) {
     93 	case BLOCK_HASHTAG:
     94 	case BLOCK_TEXT:
     95 	case BLOCK_URL:
     96 		if (!pull_str_block(cur, content, &block->block.str))
     97 			goto fail;
     98 		break;
     99 
    100 	case BLOCK_MENTION_INDEX:
    101 		if (!cursor_pull_varint_u32(cur, &block->block.mention_index))
    102 			goto fail;
    103 		break;
    104 
    105 	case BLOCK_MENTION_BECH32:
    106 		if (!pull_bech32_mention(content, cur, &block->block.mention_bech32))
    107 			goto fail;
    108 		break;
    109 
    110 	case BLOCK_INVOICE:
    111 		// we only push invoice strs here
    112 		if (!pull_invoice(content, cur, &block->block.invoice))
    113 			goto fail;
    114 		break;
    115 	}
    116 
    117 	return 1;
    118 fail:
    119 	cur->p = start;
    120 	return 0;
    121 }
    122 
    123 
    124 enum ndb_block_type ndb_get_block_type(struct ndb_block *block) {
    125 	return block->type;
    126 }
    127 
    128 // BLOCK ITERATORS
    129 void ndb_blocks_iterate_start(const char *content, struct ndb_blocks *blocks, struct ndb_block_iterator *iter) {
    130 	iter->blocks = blocks;
    131 	iter->content = content;
    132 	iter->p = blocks->blocks;
    133 }
    134 
    135 struct ndb_block *ndb_blocks_iterate_next(struct ndb_block_iterator *iter)
    136 {
    137 	struct cursor cur;
    138 	cur.start = iter->blocks->blocks;
    139 	cur.p = iter->p;
    140 	cur.end = iter->blocks->blocks + iter->blocks->blocks_size;
    141 
    142 	while (cur.p < cur.end) {
    143 		if (!pull_block(iter->content, &cur, &iter->block)) {
    144 			iter->p = cur.p;
    145 			return NULL;
    146 		} else {
    147 			iter->p = cur.p;
    148 			return &iter->block;
    149 		}
    150 	}
    151 
    152 	return NULL;
    153 }
    154 
    155 // STR BLOCKS
    156 struct ndb_str_block *ndb_block_str(struct ndb_block *block)
    157 {
    158 	switch (block->type) {
    159 	case BLOCK_HASHTAG:
    160 	case BLOCK_TEXT:
    161 	case BLOCK_URL:
    162 		return &block->block.str;
    163 	case BLOCK_MENTION_INDEX:
    164 		return NULL;
    165 	case BLOCK_MENTION_BECH32:
    166 		return &block->block.mention_bech32.str;
    167 	case BLOCK_INVOICE:
    168 		return &block->block.invoice.invstr;
    169 	}
    170 
    171 	return NULL;
    172 }
    173 
    174 const char *ndb_str_block_ptr(struct ndb_str_block *str_block) {
    175 	return str_block->str;
    176 }
    177 
    178 uint32_t ndb_str_block_len(struct ndb_str_block *str_block) {
    179 	return str_block->len;
    180 }
    181 
    182 struct nostr_bech32 *ndb_bech32_block(struct ndb_block *block) {
    183 	return &block->block.mention_bech32.bech32;
    184 }
    185 
    186 // total size including padding
    187 size_t ndb_blocks_total_size(struct ndb_blocks *blocks) {
    188 	return blocks->total_size;
    189 }
    190 
    191 void ndb_blocks_free(struct ndb_blocks *blocks) {
    192 	if ((blocks->flags & NDB_BLOCK_FLAG_OWNED) != NDB_BLOCK_FLAG_OWNED)
    193 		return;
    194 
    195 	free(blocks);
    196 }
    197 
    198 int ndb_blocks_flags(struct ndb_blocks *blocks) {
    199 	return blocks->flags;
    200 }
    201 
    202 int ndb_blocks_word_count(struct ndb_blocks *blocks) {
    203 	return blocks->words;
    204 }