commit 93cfa17bd6d24aa3326ba000ed62bc5c0a9e3cd0
parent bd7487d34d684d776cb051baa36ca9ad92b6b193
Author: William Casarin <jb55@jb55.com>
Date:   Sat, 22 Jul 2023 15:23:39 -0700
add content length to ndb_note
We don't need this for every string, but it's nice to have for content
so you don't have to strlen it if its very large.
Diffstat:
3 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/nostrdb.c b/nostrdb.c
@@ -207,6 +207,7 @@ int ndb_builder_make_str(struct ndb_builder *builder, const char *str, int len,
 int ndb_builder_set_content(struct ndb_builder *builder, const char *content,
 			    int len)
 {
+	builder->note->content_length = len;
 	return ndb_builder_make_str(builder, content, len, &builder->note->content);
 }
 
@@ -238,12 +239,14 @@ static int ndb_builder_finalize_tag(struct ndb_builder *builder,
 /// Unescape and push json strings
 static int ndb_builder_make_json_str(struct ndb_builder *builder,
 				     const char *str, int len,
-				     union packed_str *pstr)
+				     union packed_str *pstr,
+				     int *written)
 {
 	// let's not care about de-duping these. we should just unescape
 	// in-place directly into the strings table. 
 
 	const char *p, *end, *start;
+	unsigned char *builder_start;
 
 	// always try compact strings first
 	if (ndb_builder_try_compact_str(builder, str, len, pstr))
@@ -253,6 +256,7 @@ static int ndb_builder_make_json_str(struct ndb_builder *builder,
 	start = str; // Initialize start to the beginning of the string
 
 	*pstr = ndb_offset_str(builder->strings.p - builder->strings.start);
+	builder_start = builder->strings.p;
 
 	for (p = str; p < end; p++) {
 		if (*p == '\\' && p+1 < end) {
@@ -313,6 +317,9 @@ static int ndb_builder_make_json_str(struct ndb_builder *builder,
 		return 0;
 	}
 
+	if (written)
+		*written = builder->strings.p - builder_start;
+
 	// TODO: dedupe these!?
 	return cursor_push_byte(&builder->strings, '\0');
 }
@@ -321,7 +328,7 @@ static int ndb_builder_push_json_tag(struct ndb_builder *builder,
 				     const char *str, int len)
 {
 	union packed_str pstr;
-	if (!ndb_builder_make_json_str(builder, str, len, &pstr))
+	if (!ndb_builder_make_json_str(builder, str, len, &pstr, NULL))
 		return 0;
 	return ndb_builder_finalize_tag(builder, pstr);
 }
@@ -468,11 +475,15 @@ int ndb_note_from_json(const char *json, int len, struct ndb_note **note,
 				// content
 				tok = &parser.toks[i+1];
 				union packed_str pstr;
+				tok_len = toksize(tok);
+				int written;
 				if (!ndb_builder_make_json_str(&parser.builder,
 							json + tok->start,
-							toksize(tok), &pstr)) {
+							tok_len, &pstr,
+							&written)) {
 					return 0;
 				}
+				parser.builder.note->content_length = written;
 				parser.builder.note->content = pstr;
 			}
 		} else if (start[0] == 't' && jsoneq(json, tok, tok_len, "tags")) {
diff --git a/nostrdb.h b/nostrdb.h
@@ -40,6 +40,7 @@ struct ndb_note {
 
 	uint32_t created_at;
 	uint32_t kind;
+	uint32_t content_length;
 	union packed_str content;
 	uint32_t strings;
 	uint32_t json;
@@ -84,6 +85,7 @@ static inline int ndb_str_is_packed(union packed_str str)
 	return (str.offset >> 31) & 0x1;
 }
 
+
 static inline const char * ndb_note_str(struct ndb_note *note,
 					union packed_str *str)
 {
@@ -146,6 +148,11 @@ static inline const char * ndb_note_content(struct ndb_note *note)
 	return ndb_note_str(note, ¬e->content);
 }
 
+static inline uint32_t ndb_note_content_length(struct ndb_note *note)
+{
+	return note->content_length;
+}
+
 static inline struct ndb_note * ndb_note_from_bytes(unsigned char *bytes)
 {
 	struct ndb_note *note = (struct ndb_note *)bytes;
diff --git a/test.c b/test.c
@@ -108,7 +108,7 @@ static void test_parse_contact_list()
 	size = ndb_note_from_json((const char*)json, written, ¬e, buf, alloc_size);
 	printf("ndb_note_from_json size %d\n", size);
 	assert(size > 0);
-	assert(size == 59058);
+	assert(size == 59062);
 
 	const char* expected_content = 
 	"{\"wss://nos.lol\":{\"write\":true,\"read\":true},"
@@ -123,6 +123,11 @@ static void test_parse_contact_list()
 	assert(!strcmp(expected_content, ndb_note_content(note)));
 	assert(ndb_note_created_at(note) == 1689904312);
 	assert(ndb_note_kind(note) == 3);
+	//printf("note content length %d\n", ndb_note_content_length(note));
+	printf("ndb_content_len %d, expected_len %ld\n",
+			ndb_note_content_length(note),
+			strlen(expected_content));
+	assert(ndb_note_content_length(note) == strlen(expected_content));
 
 	write_file("test_contacts_ndb_note", (unsigned char *)note, size);
 	printf("wrote test_contacts_ndb_note (raw ndb_note)\n");