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

Reply to this note

Please Login to reply.

Discussion

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

This code snippet looks awesome 🔥🔥in Amethyst thanks to the formatting support 👍

#[0]