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, ¬e->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