commit eb469b526aaf467533f35bc9b36aeeea6bf0aac9
parent 61d66748fb19d9b351be4c06f4741264363c8e5f
Author: William Casarin <jb55@jb55.com>
Date: Thu, 20 Jul 2023 14:17:55 -0700
json: support tag parsing
Also greatly simplify the iterator so you can quickly pull out string
values.
Diffstat:
M | nostrdb.c | | | 61 | +++++++++++++++++++++++++++++++++++++++---------------------- |
M | nostrdb.h | | | 20 | ++++++++++++++++---- |
M | test.c | | | 42 | +++++++++++++++++++++++++++++++----------- |
3 files changed, 86 insertions(+), 37 deletions(-)
diff --git a/nostrdb.c b/nostrdb.c
@@ -177,20 +177,40 @@ static inline int toksize(jsmntok_t *tok) {
return tok->end - tok->start;
}
+// Push a json array into an ndb tag ["p", "abcd..."] -> struct ndb_tag
static inline int
-build_tag_from_json_tokens(struct ndb_json_parser *p, jsmntok_t *tag) {
- printf("tag %.*s %d\n", toksize(tag), p->json + tag->start, tag->type);
+ndb_builder_tag_from_json_array(struct ndb_json_parser *p, jsmntok_t *array) {
+ jsmntok_t *str_tok;
+ const char *str;
+
+ if (array->size == 0)
+ return 0;
+
+ if (!ndb_builder_new_tag(&p->builder))
+ return 0;
+
+ for (int i = 0; i < array->size; i++) {
+ str_tok = &array[i+1];
+ str = p->json + str_tok->start;
+
+ if (!ndb_builder_push_tag_str(&p->builder, str, toksize(str_tok)))
+ return 0;
+ }
return 1;
}
+// Push json tags into ndb data
+// [["t", "hashtag"], ["p", "abcde..."]] -> struct ndb_tags
static inline int
ndb_builder_process_json_tags(struct ndb_json_parser *p, jsmntok_t *array) {
jsmntok_t *tag = array;
- printf("json_tags %.*s %d\n", toksize(tag), p->json + tag->start, tag->type);
+
+ if (array->size == 0)
+ return 1;
for (int i = 0; i < array->size; i++) {
- if (!build_tag_from_json_tokens(p, &tag[i+1]))
+ if (!ndb_builder_tag_from_json_array(p, &tag[i+1]))
return 0;
tag += array->size;
}
@@ -289,26 +309,23 @@ ndb_builder_set_kind(struct ndb_builder *builder, uint32_t kind) {
}
int
-ndb_builder_add_tag(struct ndb_builder *builder, const char **strs, uint16_t num_strs) {
- int i;
- union packed_str pstr;
- const char *str;
- struct ndb_tag tag;
-
+ndb_builder_new_tag(struct ndb_builder *builder) {
builder->note->tags.count++;
- tag.count = num_strs;
+ struct ndb_tag tag = {0};
+ builder->current_tag = (struct ndb_tag *)builder->note_cur.p;
+ return cursor_push_tag(&builder->note_cur, &tag);
+}
- if (!cursor_push_tag(&builder->note_cur, &tag))
+/// Push an element to the current tag
+///
+/// Basic idea is to call ndb_builder_new_tag
+inline int
+ndb_builder_push_tag_str(struct ndb_builder *builder, const char *str, int len) {
+ union packed_str pstr;
+ if (!ndb_builder_make_string(builder, str, len, &pstr))
return 0;
-
- for (i = 0; i < num_strs; i++) {
- str = strs[i];
- if (!ndb_builder_make_string(builder, str, strlen(str), &pstr))
- return 0;
- if (!cursor_push_u32(&builder->note_cur, pstr.offset))
- return 0;
- }
-
+ if (!cursor_push_u32(&builder->note_cur, pstr.offset))
+ return 0;
+ builder->current_tag->count++;
return 1;
}
-
diff --git a/nostrdb.h b/nostrdb.h
@@ -55,6 +55,7 @@ struct ndb_builder {
struct cursor strings;
struct cursor str_indices;
struct ndb_note *note;
+ struct ndb_tag *current_tag;
};
struct ndb_iterator {
@@ -74,7 +75,8 @@ void ndb_builder_set_signature(struct ndb_builder *builder, unsigned char *signa
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_add_tag(struct ndb_builder *builder, const char **strs, uint16_t num_strs);
+int ndb_builder_new_tag(struct ndb_builder *builder);
+int ndb_builder_push_tag_str(struct ndb_builder *builder, const char *str, int len);
// BYE BUILDER
static inline int
@@ -83,13 +85,23 @@ ndb_str_is_packed(union packed_str str) {
}
static inline const char *
-ndb_note_string(struct ndb_note *note, union packed_str *str) {
+ndb_note_str(struct ndb_note *note, union packed_str *str) {
if (ndb_str_is_packed(*str))
return str->packed.str;
return ((const char *)note) + note->strings + str->offset;
}
+static inline const char *
+ndb_tag_str(struct ndb_note *note, struct ndb_tag *tag, int ind) {
+ return ndb_note_str(note, &tag->strs[ind]);
+}
+
+static inline const char *
+ndb_iter_tag_str(struct ndb_iterator *iter, int ind) {
+ return ndb_tag_str(iter->note, iter->tag, ind);
+}
+
static inline unsigned char *
ndb_note_id(struct ndb_note *note) {
return note->id;
@@ -112,7 +124,7 @@ ndb_note_created_at(struct ndb_note *note) {
static inline const char *
ndb_note_content(struct ndb_note *note) {
- return ndb_note_string(note, ¬e->content);
+ return ndb_note_str(note, ¬e->content);
}
static inline struct ndb_note *
@@ -156,7 +168,7 @@ ndb_note_tag_index(struct ndb_note *note, struct ndb_tag *tag, int index) {
return 0;
}
- return ndb_note_string(note, &tag->strs[index]);
+ return ndb_note_str(note, &tag->strs[index]);
}
static inline int
diff --git a/test.c b/test.c
@@ -22,10 +22,7 @@ static void test_basic_event() {
unsigned char sig[64];
memset(sig, 3, 64);
-
const char *hex_pk = "5d9b81b2d4d5609c5565286fc3b511dc6b9a1b3d7d1174310c624d61d1f82bb9";
- const char *tag[] = { "p", hex_pk };
- const char *word_tag[] = { "word", "words", "w" };
ok = ndb_builder_new(b, buf, sizeof(buf));
assert(ok);
@@ -39,8 +36,15 @@ static void test_basic_event() {
ndb_builder_set_id(b, id); assert(ok);
ndb_builder_set_pubkey(b, pubkey); assert(ok);
ndb_builder_set_signature(b, sig); assert(ok);
- ok = ndb_builder_add_tag(b, tag, ARRAY_SIZE(tag)); assert(ok);
- ok = ndb_builder_add_tag(b, word_tag, ARRAY_SIZE(word_tag)); assert(ok);
+
+ ok = ndb_builder_new_tag(b); assert(ok);
+ ok = ndb_builder_push_tag_str(b, "p", 1); assert(ok);
+ ok = ndb_builder_push_tag_str(b, hex_pk, 64); assert(ok);
+
+ ok = ndb_builder_new_tag(b); assert(ok);
+ ok = ndb_builder_push_tag_str(b, "word", 4); assert(ok);
+ ok = ndb_builder_push_tag_str(b, "words", 5); assert(ok);
+ ok = ndb_builder_push_tag_str(b, "w", 1); assert(ok);
ok = ndb_builder_finalize(b, ¬e);
assert(ok);
@@ -53,8 +57,8 @@ static void test_basic_event() {
ok = ndb_tags_iterate_start(note, it);
assert(ok);
assert(it->tag->count == 2);
- const char *p = ndb_note_string(note, &it->tag->strs[0]);
- const char *hpk = ndb_note_string(note, &it->tag->strs[1]);
+ const char *p = ndb_iter_tag_str(it, 0);
+ const char *hpk = ndb_iter_tag_str(it, 1);
assert(hpk);
assert(!ndb_str_is_packed(it->tag->strs[1]));
assert(!strcmp(hpk, hex_pk));
@@ -63,9 +67,9 @@ static void test_basic_event() {
ok = ndb_tags_iterate_next(it);
assert(ok);
assert(it->tag->count == 3);
- assert(!strcmp(ndb_note_string(note, &it->tag->strs[0]), "word"));
- assert(!strcmp(ndb_note_string(note, &it->tag->strs[1]), "words"));
- assert(!strcmp(ndb_note_string(note, &it->tag->strs[2]), "w"));
+ assert(!strcmp(ndb_iter_tag_str(it, 0), "word"));
+ assert(!strcmp(ndb_iter_tag_str(it, 1), "words"));
+ assert(!strcmp(ndb_iter_tag_str(it, 2), "w"));
ok = ndb_tags_iterate_next(it);
assert(!ok);
@@ -98,16 +102,32 @@ static void test_parse_json() {
#define HEX_ID "5004a081e397c6da9dc2f2d6b3134006a9d0e8c1b46689d9fe150bb2f21a204d"
#define HEX_PK "b169f596968917a1abeb4234d3cf3aa9baee2112e58998d17c6db416ad33fe40"
static const char *json =
- "{\"id\": \"" HEX_ID "\",\"pubkey\": \"" HEX_PK "\",\"created_at\": 1689836342,\"kind\": 1,\"tags\": [[\"p\",\"" HEX_ID "\"], [\"word\", \"words\"]],\"content\": \"共通語\",\"sig\": \"e4d528651311d567f461d7be916c37cbf2b4d530e672f29f15f353291ed6df60c665928e67d2f18861c5ca88\"}";
+ "{\"id\": \"" HEX_ID "\",\"pubkey\": \"" HEX_PK "\",\"created_at\": 1689836342,\"kind\": 1,\"tags\": [[\"p\",\"" HEX_ID "\"], [\"word\", \"words\", \"w\"]],\"content\": \"共通語\",\"sig\": \"e4d528651311d567f461d7be916c37cbf2b4d530e672f29f15f353291ed6df60c665928e67d2f18861c5ca88\"}";
+ int ok;
ndb_note_from_json(json, strlen(json), ¬e, buffer, sizeof(buffer));
const char *content = ndb_note_content(note);
unsigned char *id = ndb_note_id(note);
+
hex_encode(id, 32, hex_id, sizeof(hex_id));
assert(!strcmp(content, "共通語"));
assert(!strcmp(HEX_ID, hex_id));
+
+ assert(note->tags.count == 2);
+
+ struct ndb_iterator iter, *it = &iter;
+ ok = ndb_tags_iterate_start(note, it); assert(ok);
+ assert(it->tag->count == 2);
+ assert(!strcmp(ndb_iter_tag_str(it, 0), "p"));
+ assert(!strcmp(ndb_iter_tag_str(it, 1), HEX_ID));
+
+ ok = ndb_tags_iterate_next(it); assert(ok);
+ assert(it->tag->count == 3);
+ assert(!strcmp(ndb_iter_tag_str(it, 0), "word"));
+ assert(!strcmp(ndb_iter_tag_str(it, 1), "words"));
+ assert(!strcmp(ndb_iter_tag_str(it, 2), "w"));
}
int main(int argc, const char *argv[]) {