From 1c0a06a6b73282084e32b51a825c1882117e5e8c Mon Sep 17 00:00:00 2001 From: MooZ Date: Mon, 4 Nov 2024 20:07:53 +0100 Subject: [PATCH] Section rework wip --- section.c | 124 ++++++++++++++++++++++++++++++++++++++++++++ section.h | 42 +++++++++++++-- test/CMakeLists.txt | 1 - test/section.c | 52 ++++++++++++++++++- 4 files changed, 213 insertions(+), 6 deletions(-) diff --git a/section.c b/section.c index 3d54170..f138858 100644 --- a/section.c +++ b/section.c @@ -116,3 +116,127 @@ void section_delete(Section *ptr, int n) { } free(ptr); } + +// Reset a section array. +void section_array_reset(SectionArray *arr) { + assert(arr != NULL); + if(arr->data != NULL) { + for(size_t i=0; icount; i++) { + free(arr->data[i].name); + free(arr->data[i].output); + free(arr->data[i].description); + section_reset(&arr->data[i]); + } + } + arr->count = 0; +} + +// Release section array memory. +void section_array_delete(SectionArray *arr) { + assert(arr != NULL); + section_array_reset(arr); + free(arr->data); + arr->data = NULL; + arr->capacity = 0; +} + +// Check if 2 sections overlaps. +// \return 1 Both sections has the same time and overlaps +// \return 0 Sections don't overlap +// \return -1 Sections overlap but they are not of the same type. +static int section_overlap(const Section *a, const Section *b) { + assert(a != NULL); + assert(b != NULL); + + int ret = 0; + + if(a->page == b->page) { + if(a->logical > b->logical) { + const Section *tmp = b; + b = a; + a = tmp; + } + if(b->logical <= (a->logical + a->size)) { + if(a->type == b->type) { + ret = 1; + } else { + ret = -1; + } + } + } + return ret; +} + +static inline uint16_t minu16(uint16_t a, uint16_t b) { + return (a < b) ? a : b; +} + +static inline uint16_t maxi32(int32_t a, int32_t b) { + return (a > b) ? a : b; +} + +// Merge 2 sections the 2nd section into the 1st one. +static void section_merge(Section *a, const Section *b) { + assert(a != NULL); + assert(b != NULL); + + uint16_t begin = minu16(a->logical, b->logical); + int32_t end = maxi32(a->logical+a->size, b->logical+b->size); + a->logical = begin; + a->size = end - begin; +} + +// Add a new section. +int section_array_add(SectionArray *arr, const Section* in) { + assert(arr != NULL); + assert(in != NULL); + + int ret = -1;//todo + size_t i; + // Search for overlapping section. + for(i=0; icount; i++) { + int overlap = section_overlap(&arr->data[i], in); + if(overlap == 1) { + section_merge(&arr->data[i], in); + INFO_MSG("Section %s has been merged with %s!", arr->data[i].name, in->name); + break; + } else if(overlap == -1) { + WARNING_MSG("Section %s and %s overlaps! %x %x.%x", arr->data[i].name, in->name); + break; + } + } + + if(i >= arr->count) { + // Check if we need to expand section array buffer + if(i >= arr->capacity) { + size_t n = arr->capacity + 4U; + Section *ptr = realloc(arr->data, n*sizeof(Section)); + if(ptr == NULL) { + ERROR_MSG("Failed to expand section array buffer", strerror(errno)); + } else { + arr->data = ptr; + arr->capacity = n; + ret = true; + } + } else { + ret = true; + } + + // Append new section. + if(ret) { + arr->data[arr->count++] = *in; + } + } + return ret; +} + +// Retrieve the ith section from the array. +const Section* section_array_get(SectionArray *arr, size_t i) { + const Section *ret = NULL; + if(arr != NULL) { + if((arr->data != NULL) && (i < arr->count)) { + ret = &arr->data[i]; + } + } + return ret; +} \ No newline at end of file diff --git a/section.h b/section.h index deea575..256f7f1 100644 --- a/section.h +++ b/section.h @@ -99,10 +99,10 @@ void section_reset(Section *s); /// Group section per output filename and sort them in page/logical address order. /// \param [in out] ptr Sections. /// \param [in] n Number of sections to sort. -void section_sort(Section *ptr, size_t n); +void section_sort(Section *ptr, size_t n); // [todo] will be removed /// Delete sections. -void section_delete(Section *ptr, int n); +void section_delete(Section *ptr, int n); // [todo] will be removed // Load sections from a JSON file. // \param [out] out Loaded sections. @@ -110,7 +110,7 @@ void section_delete(Section *ptr, int n); // \param [in] filename Input filename. // \return true if the sections contained in the file were succesfully loaded. // \return false if an error occured. -bool section_load(Section **out, int *n, const char *filename); +bool section_load(Section **out, int *n, const char *filename); // [todo] use SectionArray // Save sections to a JSON file. // \param [in] ptr Sections to be saved. @@ -118,6 +118,40 @@ bool section_load(Section **out, int *n, const char *filename); // \param [in] filename Output filename. // \return true if the sections were succesfully saved. // \return false if an error occured. -bool section_save(const Section *ptr, int n, const char *filename); +bool section_save(const Section *ptr, int n, const char *filename); // [todo] use SectionArray + +// Section array +typedef struct { + Section *data; ///< Pointer to section array. + size_t count; ///< Number of sections currently in use. + size_t capacity; ///< Number the section array can hold. + // [todo] index array of sorted sections ? +} SectionArray; + +/// Reset a section array. +/// \note The internal data pointer will not be freed. +/// \param [in out] arr Section array to be reseted. +void section_array_reset(SectionArray *arr); + +/// Release section array memory. +/// \param [in out] arr Section array. +void section_array_delete(SectionArray *arr); + +/// Add a new section. +/// Note that if the section overlaps an already existing one, it will be merged if both sections have the +/// same type. +/// \param [in out] arr Section array the section will be added to. +/// \param [in] in Section that will be added to the section array. +/// \return 1 if the section was succesfully added. +/// \return 0 if the section was merged with one from the section array. +/// \return -1 if the section can not be merged or if there is not enough memory to add a new one. +int section_array_add(SectionArray *arr, const Section* in); + +/// Retrieve the ith section from the array. +/// \param [in] arr Section array. +/// \param [in] i Index of the section to be retrieved. +/// \return A pointer to the section if the index is within the section array bounds. +/// \return NULL if the index is out of the section array bounds. +const Section* section_array_get(SectionArray *arr, size_t i); #endif // ETRIPATOR_SECTION_H diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index bd888d1..a13cb86 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -128,7 +128,6 @@ add_unit_test( NAME section SOURCES section.c - ${PROJECT_SOURCE_DIR}/section.c ${PROJECT_SOURCE_DIR}/section/load.c ${PROJECT_SOURCE_DIR}/message.c ${PROJECT_SOURCE_DIR}/jsonhelpers.c diff --git a/test/section.c b/test/section.c index 65509f3..0814cec 100644 --- a/test/section.c +++ b/test/section.c @@ -34,7 +34,7 @@ ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ */ #include -#include "section.h" +#include "../section.c" #include "message.h" #include "message/console.h" @@ -175,9 +175,59 @@ MunitResult section_load_test(const MunitParameter params[], void* fixture) { return MUNIT_OK; } +MunitResult section_overlap_test(const MunitParameter params[], void* fixture) { + Section a = { + .type = SECTION_TYPE_CODE, + .page = 0x01, + }; + Section b = { + .type = SECTION_TYPE_CODE, + .page = 0x01, + }; + + a.logical = 0xe000; + a.size = 0x100; + + b.logical = 0xe010; + b.size = 0x40; + + munit_assert_int(section_overlap(&a, &b), ==, 1); + + b.type = SECTION_TYPE_DATA; + munit_assert_int(section_overlap(&a, &b), ==, -1); + + a.type = SECTION_TYPE_DATA; + a.logical = 0x0200; + a.size = 0x10; + + b.logical = 0x01e0; + b.size = 0x50; + + munit_assert_int(section_overlap(&a, &b), ==, 1); + + b.page = 0x02; + munit_assert_int(section_overlap(&a, &b), ==, 0); + + b.page = a.page; + b.size = 0x01; + munit_assert_int(section_overlap(&a, &b), ==, 0); + + return MUNIT_OK; +} + + +MunitResult section_add_test(const MunitParameter params[], void* fixture) { + // [todo] add sections + // [todo] add one that merge + // [todo] add one with merge+error + return MUNIT_OK; +} + static MunitTest section_tests[] = { { "/sort", section_sort_test, setup, tear_down, MUNIT_TEST_OPTION_NONE, NULL }, { "/load", section_load_test, setup, tear_down, MUNIT_TEST_OPTION_NONE, NULL }, + { "/overlap", section_overlap_test, setup, tear_down, MUNIT_TEST_OPTION_NONE, NULL }, + { "/add", section_add_test, setup, tear_down, MUNIT_TEST_OPTION_NONE, NULL }, { NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL } };