From 9e874301350a70a1ba40b5508878d559f68f8f4a Mon Sep 17 00:00:00 2001 From: Mosder Date: Tue, 28 Jul 2026 16:38:04 +0200 Subject: refactor: generalized dynamic arrays with structures/array.h --- analyzer/parser/fight_results/fight_results.c | 77 ++++++++++++++------------- analyzer/parser/fight_results/fight_results.h | 11 ++-- analyzer/parser/parser.c | 37 ++++++------- analyzer/parser/parser.h | 14 ++--- analyzer/parser/parser_defs.h | 6 +-- 5 files changed, 66 insertions(+), 79 deletions(-) (limited to 'analyzer/parser') diff --git a/analyzer/parser/fight_results/fight_results.c b/analyzer/parser/fight_results/fight_results.c index 3adf67b..942d9b4 100644 --- a/analyzer/parser/fight_results/fight_results.c +++ b/analyzer/parser/fight_results/fight_results.c @@ -13,32 +13,40 @@ #include "parser/fight_results/gear.h" #include "parser/fight_results/gear_info.h" #include "parser/fight_results/orb.h" -#include "parser/structs.h" #include "utils/memory.h" #include "utils/roman.h" // function to cleanup fight results to be used in ParsedData struct void cleanup_fight_results(void *data) { FightResults *fight_results = data; - for (size_t i = 0; i < fight_results->num_friendly; i++) { - FriendlyResults friendly = fight_results->friendly_results[i]; - free(friendly.name); - for (size_t j = 0; j < friendly.num_items; j++) - free(friendly.items[j].data); - free(friendly.items); - } - for (size_t i = 0; i < fight_results->num_enemy; i++) { - free(fight_results->enemy_results[i].name); - } - free(fight_results->friendly_results); - free(fight_results->enemy_results); + array_destroy(fight_results->friendly_results); + array_destroy(fight_results->enemy_results); } -byte_t *find_fight_results(TCPStream *stream, int offset, int *length) { - byte_t *start = memmem(stream->data + offset, stream->len - offset, FIGHT_RESULTS_START, strlen(FIGHT_RESULTS_START)); +// function to cleanup FriendlyResults in DynArray +void cleanup_friendly_results(void *results) { + FriendlyResults *friendly = results; + free(friendly->name); + array_destroy(friendly->items); +} + +// function to cleanup EnemyResults in DynArray +void cleanup_enemy_results(void *results) { + EnemyResults *enemy = results; + free(enemy->name); +} + +// function to cleanup Item in DynArray +void cleanup_item(void *item) { + Item *it = item; + free(it->data); +} + +byte_t *find_fight_results(byte_t *bytes, size_t bytes_count, int *length) { + byte_t *start = memmem(bytes, bytes_count, FIGHT_RESULTS_START, strlen(FIGHT_RESULTS_START)); byte_t *end = NULL; if (start) - end = memmem(start, stream->len - (start - stream->data), FIGHT_RESULTS_END, strlen(FIGHT_RESULTS_END)); + end = memmem(start, bytes_count - (start - bytes), FIGHT_RESULTS_END, strlen(FIGHT_RESULTS_END)); *length = end ? (int)(end - start + strlen(FIGHT_RESULTS_END)) : -1; return start; } @@ -48,7 +56,7 @@ void get_stars(char *buffer, int incr_above_b1) { sprintf(buffer, " (%c%d)", star_types[incr_above_b1 / 3], incr_above_b1 % 3 + 1); } -void add_gear(FriendlyResults *results, size_t *items_capacity, char *gears_str) { +void add_gear(DynArray *items, char *gears_str) { if (strlen(gears_str) == 0) return; @@ -106,7 +114,7 @@ void add_gear(FriendlyResults *results, size_t *items_capacity, char *gears_str) item.type = EPIC; break; } - results->items = array_append(results->items, sizeof(Item), &results->num_items, items_capacity, &item); + array_append(items, &item); cleanup_struct(&gear_info, gear_info_fields, ARR_LEN(gear_info_fields)); @@ -119,7 +127,7 @@ void add_gear(FriendlyResults *results, size_t *items_capacity, char *gears_str) sprintf(buffer, "%sorb %s", get_artifact_size_from_id(orb.size), get_orb_name_from_id(orb.id)); Item item = {.data = strdup(buffer), .type = ORB}; - results->items = array_append(results->items, sizeof(Item), &results->num_items, items_capacity, &item); + array_append(items, &item); cleanup_struct(&orb, orb_fields, ARR_LEN(orb_fields)); } @@ -128,7 +136,7 @@ void add_gear(FriendlyResults *results, size_t *items_capacity, char *gears_str) } while (gears_separator); } -void add_drifs(FriendlyResults *results, size_t *items_capacity, char *drifs_str) { +void add_drifs(DynArray *items, char *drifs_str) { if (strlen(drifs_str) == 0) return; @@ -144,13 +152,13 @@ void add_drifs(FriendlyResults *results, size_t *items_capacity, char *drifs_str drifs_str = drifs_separator + strlen(SEPARATOR_DRIF); Item item = {.data = strdup(drif.name), .type = DRIF}; - results->items = array_append(results->items, sizeof(Item), &results->num_items, items_capacity, &item); + array_append(items, &item); cleanup_struct(&drif, drif_fields, ARR_LEN(drif_fields)); } while (drifs_separator); } -void add_items(FriendlyResults *results, size_t *items_capacity, char *items_str) { +void add_items(DynArray *items, char *items_str) { if (strlen(items_str) == 0) return; @@ -168,7 +176,7 @@ void add_items(FriendlyResults *results, size_t *items_capacity, char *items_str items_str = items_separator + strlen(SEPARATOR_ITEMS); Item item = {.data = strdup(buffer), .type = NORMAL}; - results->items = array_append(results->items, sizeof(Item), &results->num_items, items_capacity, &item); + array_append(items, &item); } while (items_separator); } @@ -181,16 +189,14 @@ FriendlyResults parse_to_friendly(EntityResults entity_results) { .level = entity_results.level, .psycho = entity_results.psycho, .splinters = entity_results.splinters, - .num_items = 0, .saturation = 0 }; // create items array and add to it gear, drifs and items - results.items = safe_malloc(INIT_ITEMS_CAPACITY * sizeof(Item)); - size_t items_cap = INIT_ITEMS_CAPACITY; - add_gear(&results, &items_cap, entity_results.gear); - add_drifs(&results, &items_cap, entity_results.drifs); - add_items(&results, &items_cap, entity_results.items); + results.items = array_new(sizeof(Item), INIT_ITEMS_CAPACITY, cleanup_item); + add_gear(&results.items, entity_results.gear); + add_drifs(&results.items, entity_results.drifs); + add_items(&results.items, entity_results.items); if (strlen(entity_results.saturation) > 0) { int saturation_id; @@ -216,13 +222,8 @@ ParsedData parse_fight_results(byte_t *data, size_t length) { FightResults *results = safe_malloc(sizeof(FightResults)); - results->friendly_results = safe_malloc(INIT_ENTITIES_PER_SIDE * sizeof(FriendlyResults)); - results->num_friendly = 0; - size_t friendly_cap = INIT_ENTITIES_PER_SIDE; - - results->enemy_results = safe_malloc(INIT_ENTITIES_PER_SIDE * sizeof(EnemyResults)); - results->num_enemy = 0; - size_t enemy_cap = INIT_ENTITIES_PER_SIDE; + results->friendly_results = array_new(sizeof(FriendlyResults), INIT_ENTITIES_PER_SIDE, cleanup_friendly_results); + results->enemy_results = array_new(sizeof(EnemyResults), INIT_ENTITIES_PER_SIDE, cleanup_enemy_results); byte_t *entity_separator; do { @@ -236,12 +237,12 @@ ParsedData parse_fight_results(byte_t *data, size_t length) { switch (entity_results.team) { case TEAM_FRIEND: { FriendlyResults res = parse_to_friendly(entity_results); - results->friendly_results = array_append(results->friendly_results, sizeof(FriendlyResults), &results->num_friendly, &friendly_cap, &res); + array_append(&results->friendly_results, &res); break; } case TEAM_ENEMY: { EnemyResults res = parse_to_enemy(entity_results); - results->enemy_results = array_append(results->enemy_results, sizeof(EnemyResults), &results->num_enemy, &enemy_cap, &res); + array_append(&results->enemy_results, &res); break; } } diff --git a/analyzer/parser/fight_results/fight_results.h b/analyzer/parser/fight_results/fight_results.h index ec90394..03b3e7b 100644 --- a/analyzer/parser/fight_results/fight_results.h +++ b/analyzer/parser/fight_results/fight_results.h @@ -2,7 +2,7 @@ // utilities for parsing the fight results data #include "parser/parser_defs.h" -#include "utils/tcp.h" +#include "structures/array.h" #ifndef FIGHT_RESULTS_H #define FIGHT_RESULTS_H @@ -29,8 +29,7 @@ typedef struct { char *name; int exp; int gold; - Item *items; - size_t num_items; + DynArray items; int level; int psycho; int splinters; @@ -48,10 +47,8 @@ typedef struct { // entire fight resutls typedef struct { - size_t num_friendly; - FriendlyResults *friendly_results; - size_t num_enemy; - EnemyResults *enemy_results; + DynArray friendly_results; + DynArray enemy_results; } FightResults; extern find_function_t find_fight_results; diff --git a/analyzer/parser/parser.c b/analyzer/parser/parser.c index 07980e5..9265153 100644 --- a/analyzer/parser/parser.c +++ b/analyzer/parser/parser.c @@ -5,8 +5,16 @@ #include "parser/find_parse_functions.h" #include "utils/memory.h" +// function to cleanup ParsedData in DynArray +void cleanup_parsed_data(void *parsed_data) { + ParsedData *data = parsed_data; + if (data->data_cleanup) + data->data_cleanup(data->data); + free(data->data); +} + // find earliest data to parse in stream -byte_t *find_earliest_data(TCPStream *stream, int stream_offset, int *earliest_length, parse_function_t **earliest_parse_fun) { +byte_t *find_earliest_data(TCPStream *stream, size_t stream_offset, int *earliest_length, parse_function_t **earliest_parse_fun) { byte_t *earliest_data = NULL; for (size_t i = 0; i < ARR_LEN(all_find_parse_functions); i++) { // ignore if not correct stream @@ -14,7 +22,7 @@ byte_t *find_earliest_data(TCPStream *stream, int stream_offset, int *earliest_l continue; int length; - byte_t *data = all_find_parse_functions[i].find_fn(stream, stream_offset, &length); + byte_t *data = all_find_parse_functions[i].find_fn(stream->bytes.data + stream_offset, stream->bytes.count - stream_offset, &length); // if it's the first found or earlier than earliest - save it if (data && (!earliest_data || data < earliest_data)) { earliest_data = data; @@ -25,12 +33,10 @@ byte_t *find_earliest_data(TCPStream *stream, int stream_offset, int *earliest_l return earliest_data; } -ParsedData *parse_stream(TCPStream *stream, size_t *parsed_len, size_t *n_parsed_data) { - size_t parsed_data_capacity = INIT_PARSED_DATA_CAPACITY; - ParsedData *parsed_data = safe_malloc(parsed_data_capacity * sizeof(ParsedData)); - *n_parsed_data = 0; +DynArray parse_stream(TCPStream *stream, size_t *parsed_len) { + DynArray parsed_data = array_new(sizeof(ParsedData), INIT_PARSED_DATA_CAPACITY, cleanup_parsed_data); - int stream_offset = 0; + size_t stream_offset = 0; byte_t *earliest_data; do { // find earliest data to parse @@ -41,28 +47,19 @@ ParsedData *parse_stream(TCPStream *stream, size_t *parsed_len, size_t *n_parsed // if start of data to parse was found, but not the end, then finish here // set parsed_len, so that the beginning of that data is at the beginning of the stream if (earliest_data && earliest_length == -1) { - *parsed_len = earliest_data - stream->data; + *parsed_len = earliest_data - (byte_t *)stream->bytes.data; return parsed_data; } // if data to parse was found, parse it and update the offset if (earliest_data) { ParsedData new_parsed = earliest_parse_fun(earliest_data, earliest_length); - parsed_data = array_append(parsed_data, sizeof(ParsedData), n_parsed_data, &parsed_data_capacity, &new_parsed); - stream_offset = earliest_data - stream->data + earliest_length; + array_append(&parsed_data, &new_parsed); + stream_offset = earliest_data - (byte_t *)stream->bytes.data + earliest_length; } } while (earliest_data); // if all was parsed - set parsed_len to stream_len and return the data - *parsed_len = stream->len; + *parsed_len = stream->bytes.count; return parsed_data; } - -void free_parsed_data(ParsedData *parsed_data, size_t n_parsed_data) { - for (size_t i = 0; i < n_parsed_data; i++) { - if (parsed_data[i].data_cleanup) - parsed_data[i].data_cleanup(parsed_data[i].data); - free(parsed_data[i].data); - } - free(parsed_data); -} diff --git a/analyzer/parser/parser.h b/analyzer/parser/parser.h index e7c46e8..221d3bd 100644 --- a/analyzer/parser/parser.h +++ b/analyzer/parser/parser.h @@ -1,8 +1,7 @@ // parser/parser.h // main parser file -#include "parser/fight_results/fight_results.h" -#include "parser/parser_defs.h" +#include "structures/array.h" #include "utils/tcp.h" #define INIT_PARSED_DATA_CAPACITY 4 @@ -11,13 +10,6 @@ // params: // - stream - the stream to parse // - parsed_len - pointer to inform how much of the stream was parsed (not all if e.g. start of data is there, but the end isn't yet) -// - n_parsed_data - pointer to the count of parsed data that was retrieved from the stream // returns: -// pointer to the array of parsed data -extern ParsedData *parse_stream(TCPStream *stream, size_t *parsed_len, size_t *n_parsed_data); - -// free the entire parsed data array from parse_stream function -// params: -// - parsed_data - parsed data to free -// - n_parsed_data - count of parsed data -extern void free_parsed_data(ParsedData *parsed_data, size_t n_parsed_data); +// array of parsed data +extern DynArray parse_stream(TCPStream *stream, size_t *parsed_len); diff --git a/analyzer/parser/parser_defs.h b/analyzer/parser/parser_defs.h index c64e138..5c03a09 100644 --- a/analyzer/parser/parser_defs.h +++ b/analyzer/parser/parser_defs.h @@ -18,12 +18,12 @@ typedef struct { // find the first results data of specific type in stream // params: -// - stream - stream to find the data in -// - offset - offset to start finding data from +// - bytes - stream bytes to find the data in +// - bytes_count - count of bytes in the stream // - length - length of the data or -1 if there's no end yet // returns: // pointer to the beginning of data or NULL if there's none -typedef byte_t *find_function_t(TCPStream *stream, int offset, int *length); +typedef byte_t *find_function_t(byte_t *bytes, size_t bytes_count, int *length); // parse given data of specifc type // params: -- cgit v1.2.3