Can we break this into smaller functions so it’s easier to understand?

Reply to this note

Please Login to reply.

Discussion

Yes, breaking the code into smaller functions can make it easier to understand and manage. Here's an example of how that could be done:

```c

static int parse_mentions(struct cursor *cur, struct block *block) {

const u8 *start;

struct mention_bech32_block mention = { 0 };

start = cur->p;

if (!parse_str(cur, "nostr:")) {

return 0;

}

if (!parse_bech32(cur, &mention)) {

cur->p = start;

return 0;

}

if (!validate_mention(&mention)) {

free(mention.buffer);

cur->p = start;

return 0;

}

block->type = BLOCK_MENTION_BECH32;

block->block.mention_bech32 = mention;

return 1;

}

static int parse_bech32(struct cursor *cur, struct mention_bech32_block *mention) {

const u8 *start_entity, *end;

char prefix_buffer[MAX_PREFIX_LEN];

u8 data[MAX_INPUT_LEN];

size_t data_len;

size_t input_len;

int encoding;

start_entity = cur->p;

if (!consume_str_until_whitespace(cur, MAX_PREFIX_LEN, prefix_buffer)) {

return 0;

}

end = cur->p;

input_len = end - start_entity;

if (input_len > MAX_INPUT_LEN) {

return 0;

}

data_len = decode_bech32(start_entity, input_len, data, MAX_INPUT_LEN, &encoding);

if (encoding == BECH32_ENCODING_NONE) {

return 0;

}

if (!parse_data(prefix_buffer, data, data_len, encoding, mention)) {

return 0;

}

mention->str.start = (const char*)start_entity;

mention->str.end = (const char*)end;

return 1;

}

static int parse_data(char *prefix, u8 *data, size_t data_len, int encoding, struct mention_bech32_block *mention) {

size_t len;

mention->buffer = (u8*)malloc(data_len);

if (!bech32_convert_bits(mention->buffer, &len, 8, data, data_len, 5, 0)) {

free(mention->buffer);

return 0;

}

if (strcmp(prefix, "note") == 0) {

mention->type = NOSTR_BECH32_NOTE;

} else if (strcmp(prefix, "npub") == 0) {

mention->type = NOSTR_BECH32_NPUB;

} else if (strcmp(prefix, "nprofile") == 0) {

mention->type = NOSTR_BECH32_NPROFILE;

} else if (strcmp(prefix, "nevent") == 0) {

mention->type = NOSTR_BECH32_NEVENT;

} else if (strcmp(prefix, "nrelay") == 0) {

mention->type = NOSTR_BECH32_NRELAY;

} else if (strcmp(prefix, "naddr") == 0) {

mention->type = NOSTR_BECH32_NADDR;

} else {

free(mention->buffer);

return 0;

}

if (!parse_elements(data_len, mention, len)) {

free(mention->buffer);

return 0;

}

return 1;

}

static int parse_elements(size_t data_len, struct mention_bech32_block *mention, size_t len) {

const int MAX_VALUES = 16;

int values_count = 0;

u8 Ts[MAX_VALUES];

u8 Ls[MAX_VALUES];

u8* Vs[MAX_VALUES];

for (int i = 0; i < len - 1;) {

if (values_count == MAX_VALUES) {

return 0;

}

Ts[values_count] = mention->buffer[i++];

Ls[values_count] = mention->buffer[i++];

if (Ls[values_count] > len - i) {

return 0;

}

Vs[values_count] = &mention->buffer[i];

i += Ls[values_count];

++values_count;

}

if (!decode_and_validate_elements(mention->type, values_count, Ts, Ls, Vs, mention, data_len)) {

return 0;

}

return 1;

}

static int decode_and_validate_elements(int type, int count, u8 *Ts, u8 *Ls, u8 **Vs, struct mention_bech32_block *mention, size_t data_len) {

if (type == NOSTR_BECH32_NOTE || type == NOSTR_BECH32_NPUB) {

if (count != 1) {

return 0;

}

if (Ls[0] != 32) {

return 0;

}

if (type == NOSTR_BECH32_NOTE) {

mention->event_id = Vs[0];

} else {

mention->pubkey = Vs[0];

}

} else {

if (!decode_tlv(type, count, Ts, Ls, Vs, mention, data_len)) {

return 0;

}

}

return 1;

}

static int decode_tlv(int type, int count, u8 *Ts, u8 *Ls, u8 **Vs, struct mention_bech32_block *mention, size_t data_len) {

const int MAX_RELAYS = 16;

char *identifier = NULL;

int relay_count = 0;

for (int i = 0; i < count; ++i) {

if (Ts[i] == TLV_SPECIAL) {

if (Ls[i] != 32) {

return 0;

}

if (type == NOSTR_BECH32_NADDR) {

if (identifier != NULL) {

return 0;

}

Vs[i][Ls[i]] = 0;

identifier = (char*)Vs[i];

} else {

if (mention->pubkey != NULL) {

return 0;

}

mention->pubkey = Vs[i];

}

} else if (Ts[i] == TLV_RELAY) {

if (relay_count == MAX_RELAYS) {

return 0;

}

Vs[i][Ls[i]] = 0;

mention->relays[relay_count++] = (char*)Vs[i];

} else if (Ts[i] == TLV_AUTHOR) {

if (Ls[i] != 32 || mention->pubkey != NULL) {

return 0;

}

mention->pubkey = Vs[i];

} else if (Ts[i] == TLV_KIND) {

if (Ls[i] != sizeof(int) || mention->kind != -1) {

return 0;

}

mention->kind = *(int*)Vs[i];

} else if (type == NOSTR_BECH32_NEVENT && Ts[i] == TLV_SPECIAL) {

if (Ls[i] != 32) {

return 0;

}

if (mention->event_id != NULL) {

return 0;

}

mention->event_id = Vs[i];

}

}

if (identifier == NULL && type == NOSTR_BECH32_NADDR) {

return 0;

}

if ((identifier == NULL && type == NOSTR_BECH32_NOTE) || (mention->pubkey == NULL) ||

(mention->kind == -1) || (type == NOSTR_BECH32_NEVENT && mention->event_id == NULL)) {

return 0;

}

return 1;

}

static int validate_mention(struct mention_bech32_block *mention) {

if (mention->type == NOSTR_BECH32_NOTE || mention->type == NOSTR_BECH32_NPUB) {

if (!validate_non_tlv(mention, 32)) {

return 0;

}

} else {

if (!validate_tlv(mention)) {

return 0;

}

}

return 1;

}

static int validate_non_tlv(struct mention_bech32_block *mention, size_t expected_len) {

if (mention->buffer == NULL || expected_len != mention->buffer_length || mention->pubkey != NULL) {

return 0;

}

return 1;

}

static int validate_tlv(struct mention_bech32_block *mention) {

if (mention->buffer == NULL || mention->pubkey == NULL || mention->kind == -1) {

return 0;

}

if (mention->type == NOSTR_BECH32_NADDR) {

if (mention->identifier == NULL || mention->relays_count > 0) {

return 0;

}

} else if (mention->type == NOSTR_BECH32_NEVENT || mention->type == NOSTR_BECH32_NPROFILE) {

if (mention->event_id == NULL || mention->relays_count > 16) {

return 0;

}

} else if (mention->type == NOSTR_BECH32_NRELAY) {

if (mention->relays_count != 1 || mention->identifier != NULL) {

return 0;

}

}

return 1;

}

```

In this refactored code, each function has a clear focus and responsibility. The `parse_mentions()` function is the main entry point, while the other functions implement specific sub-tasks, such as parsing bech32 data, decoding and validating TLV data elements, and

Thx boss, this looks much cleaner

Error: Request failed with status code 400

πŸ˜‚

Error: Request failed with status code 400

And that's how far away AGI still is 🀣

I think the thread got too long

Are you trying to limit the amount are relays people can use on Damus?

wut

So I see you are

I see you have 93 relays, i would not recommend using that many in damus

Why

Why?

πŸ˜‚ πŸ€£πŸ˜‚πŸ€£