diff --git a/include/SDL3/SDL_test_compare.h b/include/SDL3/SDL_test_compare.h index 82de5d249..2aa84e00a 100644 --- a/include/SDL3/SDL_test_compare.h +++ b/include/SDL3/SDL_test_compare.h @@ -55,6 +55,19 @@ extern "C" { */ int SDLTest_CompareSurfaces(SDL_Surface *surface, SDL_Surface *referenceSurface, int allowable_error); +/** + * Compares 2 memory blocks for equality + * + * \param actual Memory used in comparison, displayed on the left + * \param size_actual Size of actual in bytes + * \param reference Reference memory, displayed on the right + * \param size_reference Size of reference in bytes + * + * \returns 0 if the left and right memory block are equal, non-zero if they are non-equal. + * + * \since This function is available since SDL 3.0.0. + */ +extern int SDLTest_CompareMemory(const void *actual, size_t size_actual, const void *reference, size_t size_reference); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/src/test/SDL_test_compare.c b/src/test/SDL_test_compare.c index 0cfda10e0..db2fd0477 100644 --- a/src/test/SDL_test_compare.c +++ b/src/test/SDL_test_compare.c @@ -149,3 +149,71 @@ int SDLTest_CompareSurfaces(SDL_Surface *surface, SDL_Surface *referenceSurface, return ret; } + +int SDLTest_CompareMemory(const void *actual, size_t size_actual, const void *reference, size_t size_reference) { + const size_t size_max = SDL_max(size_actual, size_reference); + size_t i; + struct { + const Uint8 *data; + size_t size; + } columns[2] = { + { + actual, + size_actual, + }, + { + reference, + size_reference, + }, + }; + +#define WIDTH 16 + + SDLTest_AssertCheck(size_actual == size_reference, "Sizes of memory blocks must be equal (actual=%" SDL_PRIu64 " expected=%" SDL_PRIu64 ")", (Uint64)size_actual, (Uint64)size_reference); + if (size_actual == size_reference) { + int equals; + equals = SDL_memcmp(actual, reference, size_max) == 0; + SDLTest_AssertCheck(equals, "Memory blocks contain the same data (actual | reference)"); + if (equals) { + return 0; + } + } + + for (i = 0; i < size_max; i += WIDTH) { + char line_buffer[16 + SDL_arraysize(columns) * (4 * WIDTH + 1) + (SDL_arraysize(columns) - 1) * 2 + 1]; + size_t pos = 0; + size_t col; + + pos += SDL_snprintf(line_buffer + pos, SDL_arraysize(line_buffer) - pos, "%016" SDL_PRIx64 , (Uint64)i); + + for (col = 0; col < SDL_arraysize(columns); col++) { + size_t j; + + for (j = 0; j < WIDTH; j++) { + if (i + j < columns[col].size) { + pos += SDL_snprintf(line_buffer + pos, SDL_arraysize(line_buffer) - pos, " %02x", columns[col].data[i + j]); + } else { + pos += SDL_snprintf(line_buffer + pos, SDL_arraysize(line_buffer) - pos, " "); + } + } + pos += SDL_snprintf(line_buffer + pos, SDL_arraysize(line_buffer) - pos, " "); + for (j = 0; j < WIDTH; j++) { + char c = ' '; + if (i + j < columns[col].size) { + c = columns[col].data[i + j]; + if (!SDL_isprint(c)) { + c = '.'; + } + } + pos += SDL_snprintf(line_buffer + pos, SDL_arraysize(line_buffer) - pos, "%c", c); + } + if (col < SDL_arraysize(columns) - 1) { + pos += SDL_snprintf(line_buffer + pos, SDL_arraysize(line_buffer), " |"); + } + } + SDLTest_LogError("%s", line_buffer); + SDL_assert(pos == SDL_arraysize(line_buffer) - 1); + } +#undef WIDTH + return 1; +}