damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

nostrdb.h (4903B)


      1 #ifndef NOSTRDB_H
      2 #define NOSTRDB_H
      3 
      4 #include <inttypes.h>
      5 #include "cursor.h"
      6 
      7 // these must be byte-aligned, they are directly accessing the serialized data
      8 // representation
      9 #pragma pack(push, 1)
     10 
     11 union packed_str {
     12 	uint32_t offset;
     13 
     14 	struct {
     15 		char str[3];
     16 		// we assume little endian everywhere. sorry not sorry.
     17 		unsigned char flag;
     18 	} packed;
     19 
     20 	unsigned char bytes[4];
     21 };
     22 
     23 struct ndb_tag {
     24 	uint16_t count;
     25 	union packed_str strs[0];
     26 };
     27 
     28 struct ndb_tags {
     29 	uint16_t count;
     30 	struct ndb_tag tag[0];
     31 };
     32 
     33 // v1
     34 struct ndb_note {
     35 	unsigned char version;    // v=1
     36 	unsigned char padding[3]; // keep things aligned
     37 	unsigned char id[32];
     38 	unsigned char pubkey[32];
     39 	unsigned char signature[64];
     40 
     41 	uint32_t created_at;
     42 	uint32_t kind;
     43 	union packed_str content;
     44 	uint32_t strings;
     45 	uint32_t json;
     46 
     47 	// nothing can come after tags since it contains variadic data
     48 	struct ndb_tags tags;
     49 };
     50 
     51 #pragma pack(pop)
     52 
     53 struct ndb_builder {
     54 	struct cursor note_cur;
     55 	struct cursor strings;
     56 	struct cursor str_indices;
     57 	struct ndb_note *note;
     58 	struct ndb_tag *current_tag;
     59 };
     60 
     61 struct ndb_iterator {
     62 	struct ndb_note *note;
     63 	struct ndb_tag *tag;
     64 
     65 	// current outer index
     66 	int index;
     67 };
     68 
     69 // HI BUILDER
     70 int ndb_note_from_json(const char *json, int len, struct ndb_note **, unsigned char *buf, int buflen);
     71 int ndb_builder_new(struct ndb_builder *builder, unsigned char *buf, int bufsize);
     72 int ndb_builder_finalize(struct ndb_builder *builder, struct ndb_note **note);
     73 int ndb_builder_set_content(struct ndb_builder *builder, const char *content, int len);
     74 void ndb_builder_set_signature(struct ndb_builder *builder, unsigned char *signature);
     75 void ndb_builder_set_pubkey(struct ndb_builder *builder, unsigned char *pubkey);
     76 void ndb_builder_set_id(struct ndb_builder *builder, unsigned char *id);
     77 void ndb_builder_set_kind(struct ndb_builder *builder, uint32_t kind);
     78 int ndb_builder_new_tag(struct ndb_builder *builder);
     79 int ndb_builder_push_tag_str(struct ndb_builder *builder, const char *str, int len);
     80 // BYE BUILDER
     81 
     82 static inline int ndb_str_is_packed(union packed_str str)
     83 {
     84 	return (str.offset >> 31) & 0x1;
     85 }
     86 
     87 static inline const char * ndb_note_str(struct ndb_note *note,
     88 					union packed_str *str)
     89 {
     90 	if (ndb_str_is_packed(*str))
     91 		return str->packed.str;
     92 
     93 	return ((const char *)note) + note->strings + str->offset;
     94 }
     95 
     96 static inline const char * ndb_tag_str(struct ndb_note *note,
     97 				       struct ndb_tag *tag, int ind)
     98 {
     99 	return ndb_note_str(note, &tag->strs[ind]);
    100 }
    101 
    102 static inline int ndb_tag_matches_char(struct ndb_note *note,
    103 				       struct ndb_tag *tag, int ind, char c)
    104 {
    105 	const char *str = ndb_tag_str(note, tag, ind);
    106 	if (str[0] == '\0')
    107 		return 0;
    108 	else if (str[0] == c)
    109 		return 1;
    110 	return 0;
    111 }
    112 
    113 static inline const char * ndb_iter_tag_str(struct ndb_iterator *iter,
    114 					    int ind)
    115 {
    116 	return ndb_tag_str(iter->note, iter->tag, ind);
    117 }
    118 
    119 static inline unsigned char * ndb_note_id(struct ndb_note *note)
    120 {
    121 	return note->id;
    122 }
    123 
    124 static inline unsigned char * ndb_note_pubkey(struct ndb_note *note)
    125 {
    126 	return note->pubkey;
    127 }
    128 
    129 static inline unsigned char * ndb_note_signature(struct ndb_note *note)
    130 {
    131 	return note->signature;
    132 }
    133 
    134 static inline uint32_t ndb_note_created_at(struct ndb_note *note)
    135 {
    136 	return note->created_at;
    137 }
    138 
    139 static inline const char * ndb_note_content(struct ndb_note *note)
    140 {
    141 	return ndb_note_str(note, &note->content);
    142 }
    143 
    144 static inline struct ndb_note * ndb_note_from_bytes(unsigned char *bytes)
    145 {
    146 	struct ndb_note *note = (struct ndb_note *)bytes;
    147 	if (note->version != 1)
    148 		return 0;
    149 	return note;
    150 }
    151 
    152 static inline union packed_str ndb_offset_str(uint32_t offset)
    153 {
    154 	// ensure accidents like -1 don't corrupt our packed_str
    155 	union packed_str str;
    156 	str.offset = offset & 0x7FFFFFFF;
    157 	return str;
    158 }
    159 
    160 static inline union packed_str ndb_char_to_packed_str(char c)
    161 {
    162 	union packed_str str;
    163 	str.packed.flag = 0xFF;
    164 	str.packed.str[0] = c;
    165 	str.packed.str[1] = '\0';
    166 	return str;
    167 }
    168 
    169 static inline union packed_str ndb_chars_to_packed_str(char c1, char c2)
    170 {
    171 	union packed_str str;
    172 	str.packed.flag = 0xFF;
    173 	str.packed.str[0] = c1;
    174 	str.packed.str[1] = c2;
    175 	str.packed.str[2] = '\0';
    176 	return str;
    177 }
    178 
    179 static inline const char * ndb_note_tag_index(struct ndb_note *note,
    180 					      struct ndb_tag *tag, int index)
    181 {
    182 	if (index >= tag->count) {
    183 		return 0;
    184 	}
    185 
    186 	return ndb_note_str(note, &tag->strs[index]);
    187 }
    188 
    189 static inline int ndb_tags_iterate_start(struct ndb_note *note,
    190 					 struct ndb_iterator *iter)
    191 {
    192 	iter->note = note;
    193 	iter->tag = note->tags.tag;
    194 	iter->index = 0;
    195 
    196 	return note->tags.count != 0 && iter->tag->count != 0;
    197 }
    198 
    199 static inline int ndb_tags_iterate_next(struct ndb_iterator *iter)
    200 {
    201 	struct ndb_tags *tags = &iter->note->tags;
    202 
    203 	if (++iter->index < tags->count) {
    204 		uint32_t tag_data_size = iter->tag->count * sizeof(iter->tag->strs[0]);
    205 		iter->tag = (struct ndb_tag *)(iter->tag->strs[0].bytes + tag_data_size);
    206 		return 1;
    207 	}
    208 
    209 	return 0;
    210 }
    211 
    212 #endif