From 6da5e65ce34184f125929545146dcf8fc16ca82e Mon Sep 17 00:00:00 2001 From: Joshua Saxby Date: Wed, 26 Oct 2016 21:31:57 +0100 Subject: [PATCH 01/11] Started adding some assertions --- saxbospiral/initialise.c | 7 +++++++ saxbospiral/initialise.h | 3 +++ saxbospiral/plot.c | 12 +++++++++++- saxbospiral/plot.h | 8 +++++++- 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/saxbospiral/initialise.c b/saxbospiral/initialise.c index 4c8abd3..bb95038 100644 --- a/saxbospiral/initialise.c +++ b/saxbospiral/initialise.c @@ -20,6 +20,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ +#include #include #include @@ -54,8 +55,14 @@ sxbp_spiral_t sxbp_blank_spiral() { * this converts the 0s and 1s in the data into UP, LEFT, DOWN, RIGHT * instructions which are then used to build the pattern. * returns a status_t struct with error information (if needed) + * + * Asserts: + * - That the spiral struct pointed to has its pointer attributes set to NULL */ sxbp_status_t sxbp_init_spiral(sxbp_buffer_t buffer, sxbp_spiral_t* spiral) { + // preconditional assertions + // assert(spiral->lines == NULL); + // assert(spiral->co_ord_cache.co_ords.items == NULL); // result status object sxbp_status_t result; // number of lines is number of bits of the data, + 1 for the first UP line diff --git a/saxbospiral/initialise.h b/saxbospiral/initialise.h index c77e925..e126c09 100644 --- a/saxbospiral/initialise.h +++ b/saxbospiral/initialise.h @@ -49,6 +49,9 @@ sxbp_spiral_t sxbp_blank_spiral(); * this converts the 0s and 1s in the data into UP, LEFT, DOWN, RIGHT * instructions which are then used to build the pattern. * returns a status_t struct with error information (if needed) + * + * Asserts: + * - That the spiral struct pointed to has its pointer attributes set to NULL */ sxbp_status_t sxbp_init_spiral(sxbp_buffer_t buffer, sxbp_spiral_t* spiral); diff --git a/saxbospiral/plot.c b/saxbospiral/plot.c index 103b880..9069491 100644 --- a/saxbospiral/plot.c +++ b/saxbospiral/plot.c @@ -21,6 +21,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ +#include #include #include "saxbospiral.h" @@ -31,8 +32,17 @@ extern "C"{ #endif -// returns the sum of all line lengths within the given indexes +/* + * returns the sum of all line lengths within the given indexes + * + * Asserts: + * - That the start index is less than end index + * - That end index is less than or equal to the spiral size + */ size_t sxbp_sum_lines(sxbp_spiral_t spiral, size_t start, size_t end) { + // preconditional assertions + assert(start < end); + assert(end <= spiral.size); size_t size = 0; for(size_t i = start; i < end; i++) { size += spiral.lines[i].length; diff --git a/saxbospiral/plot.h b/saxbospiral/plot.h index 0a554d4..b8ddb95 100644 --- a/saxbospiral/plot.h +++ b/saxbospiral/plot.h @@ -33,7 +33,13 @@ extern "C"{ #endif -// returns the sum of all line lengths within the given indexes +/* + * returns the sum of all line lengths within the given indexes + * + * Asserts: + * - That the start index is less than end index + * - That end index is less than or equal to the spiral size + */ size_t sxbp_sum_lines(sxbp_spiral_t spiral, size_t start, size_t end); /* From 7f61748a9f2d365af0e315e2f7744a536d58c85a Mon Sep 17 00:00:00 2001 From: Joshua Saxby Date: Thu, 27 Oct 2016 21:35:06 +0100 Subject: [PATCH 02/11] Fix some existing assertions and add some new ones --- saxbospiral/initialise.c | 4 ++-- saxbospiral/plot.c | 26 ++++++++++++++++++++++---- saxbospiral/plot.h | 19 ++++++++++++++----- tests.c | 2 +- 4 files changed, 39 insertions(+), 12 deletions(-) diff --git a/saxbospiral/initialise.c b/saxbospiral/initialise.c index bb95038..d6bae7b 100644 --- a/saxbospiral/initialise.c +++ b/saxbospiral/initialise.c @@ -61,8 +61,8 @@ sxbp_spiral_t sxbp_blank_spiral() { */ sxbp_status_t sxbp_init_spiral(sxbp_buffer_t buffer, sxbp_spiral_t* spiral) { // preconditional assertions - // assert(spiral->lines == NULL); - // assert(spiral->co_ord_cache.co_ords.items == NULL); + assert(spiral->lines == NULL); + assert(spiral->co_ord_cache.co_ords.items == NULL); // result status object sxbp_status_t result; // number of lines is number of bits of the data, + 1 for the first UP line diff --git a/saxbospiral/plot.c b/saxbospiral/plot.c index 9069491..40030af 100644 --- a/saxbospiral/plot.c +++ b/saxbospiral/plot.c @@ -36,13 +36,14 @@ extern "C"{ * returns the sum of all line lengths within the given indexes * * Asserts: - * - That the start index is less than end index - * - That end index is less than or equal to the spiral size + * - That start and end indexes are less than or equal to the spiral size + * - That spiral.lines is not NULL */ size_t sxbp_sum_lines(sxbp_spiral_t spiral, size_t start, size_t end) { // preconditional assertions - assert(start < end); + assert(start <= spiral.size); assert(end <= spiral.size); + assert(spiral.lines != NULL); size_t size = 0; for(size_t i = start; i < end; i++) { size += spiral.lines[i].length; @@ -59,11 +60,21 @@ size_t sxbp_sum_lines(sxbp_spiral_t spiral, size_t start, size_t end) { * each line segment is only one unit long, meaning multiple ones are needed for * lines longer than one unit. * returns a status struct with error information (if any) + * + * Asserts: + * - That the output struct's items pointer is NULL + * - That start and end indexes are less than or equal to the spiral size + * - That spiral.lines is not NULL */ sxbp_status_t sxbp_spiral_points( sxbp_spiral_t spiral, sxbp_co_ord_array_t* output, sxbp_co_ord_t start_point, size_t start, size_t end ) { + // preconditional assertions + assert(output->items == NULL); + assert(start <= spiral.size); + assert(end <= spiral.size); + assert(spiral.lines != NULL); // prepare result status sxbp_status_t result = {{0, 0, 0}, 0}; // the amount of space needed is the sum of all line lengths + 1 for end @@ -101,15 +112,22 @@ sxbp_status_t sxbp_spiral_points( } /* - * given a pointer to a spiral struct an limit, which is the index of the last + * given a pointer to a spiral struct and limit, which is the index of the last * line to use, calculate and store the co-ordinates of all line segments that * would make up the spiral if the current lengths and directions were used. * each line segment is only one unit long, meaning multiple ones are needed for * lines longer than one unit. The co-ords are stored in the spiral's * co_ord_cache member and are re-used if they are still valid * returns a status struct with error information (if any) + * + * Asserts: + * - That spiral->lines is not NULL + * - That limit is less than or equal to spiral->size */ sxbp_status_t sxbp_cache_spiral_points(sxbp_spiral_t* spiral, size_t limit) { + // preconditional assertions + assert(spiral->lines != NULL); + assert(limit <= spiral->size); // prepare result status sxbp_status_t result = {{0, 0, 0}, 0}; // the amount of space needed is the sum of all line lengths + 1 for end diff --git a/saxbospiral/plot.h b/saxbospiral/plot.h index b8ddb95..2449f3c 100644 --- a/saxbospiral/plot.h +++ b/saxbospiral/plot.h @@ -37,8 +37,8 @@ extern "C"{ * returns the sum of all line lengths within the given indexes * * Asserts: - * - That the start index is less than end index - * - That end index is less than or equal to the spiral size + * - That start and end indexes are less than or equal to the spiral size + * - That spiral.lines is not NULL */ size_t sxbp_sum_lines(sxbp_spiral_t spiral, size_t start, size_t end); @@ -51,6 +51,11 @@ size_t sxbp_sum_lines(sxbp_spiral_t spiral, size_t start, size_t end); * each line segment is only one unit long, meaning multiple ones are needed for * lines longer than one unit. * returns a status struct with error information (if any) + * + * Asserts: + * - That the output struct's items pointer is NULL + * - That start and end indexes are less than or equal to the spiral size + * - That spiral.lines is not NULL */ sxbp_status_t sxbp_spiral_points( sxbp_spiral_t spiral, sxbp_co_ord_array_t* output, @@ -58,13 +63,17 @@ sxbp_status_t sxbp_spiral_points( ); /* - * given a pointer to a spiral struct an limit, which is the index of the last + * given a pointer to a spiral struct and limit, which is the index of the last * line to use, calculate and store the co-ordinates of all line segments that * would make up the spiral if the current lengths and directions were used. * each line segment is only one unit long, meaning multiple ones are needed for - * lines longer than one unit. The co-ords are stored in the - * spiral's co_ord_cache member and are re-used if they are still valid + * lines longer than one unit. The co-ords are stored in the spiral's + * co_ord_cache member and are re-used if they are still valid * returns a status struct with error information (if any) + * + * Asserts: + * - That spiral->lines is not NULL + * - That limit is less than or equal to spiral->size */ sxbp_status_t sxbp_cache_spiral_points(sxbp_spiral_t* spiral, size_t limit); diff --git a/tests.c b/tests.c index 9650e53..c6ef30a 100644 --- a/tests.c +++ b/tests.c @@ -73,7 +73,7 @@ bool test_sxbp_init_spiral() { } // call init_spiral with buffer and write to blank spiral - sxbp_spiral_t output; + sxbp_spiral_t output = sxbp_blank_spiral(); sxbp_init_spiral(buffer, &output); if(output.size != expected.size) { From b7046c086c25999dd087b7ea5b835d73f4e71fd2 Mon Sep 17 00:00:00 2001 From: Joshua Saxby Date: Thu, 27 Oct 2016 21:59:33 +0100 Subject: [PATCH 03/11] Added assertions to render unit --- saxbospiral/render.c | 15 +++++++++++++++ saxbospiral/render.h | 4 ++++ 2 files changed, 19 insertions(+) diff --git a/saxbospiral/render.c b/saxbospiral/render.c index 34adf45..55808b2 100644 --- a/saxbospiral/render.c +++ b/saxbospiral/render.c @@ -20,6 +20,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ +#include #include #include #include @@ -39,8 +40,13 @@ extern "C"{ * corners of the square needed to contain the points. * NOTE: This should NEVER be called with a pointer to anything other than a * 2-item struct of type co_ord_t + * + * Asserts: + * - That spiral.co_ord_cache.co_ords.items is not NULL */ static void get_bounds(sxbp_spiral_t spiral, sxbp_co_ord_t* bounds) { + // preconditional assertions + assert(spiral.co_ord_cache.co_ords.items != NULL); sxbp_tuple_item_t min_x = 0; sxbp_tuple_item_t min_y = 0; sxbp_tuple_item_t max_x = 0; @@ -70,8 +76,15 @@ static void get_bounds(sxbp_spiral_t spiral, sxbp_co_ord_t* bounds) { * given a spiral struct and a pointer to a blank bitmap_t struct, writes data * representing a monochromatic image of the rendered spiral to the bitmap * returns a status struct with error information (if any) + * + * Asserts: + * - That image->pixels is NULL + * - That spiral.lines is not NULL */ sxbp_status_t sxbp_render_spiral(sxbp_spiral_t spiral, sxbp_bitmap_t* image) { + // preconditional assertions + assert(image->pixels == NULL); + assert(spiral.lines != NULL); // create result status struct sxbp_status_t result = {{0, 0, 0}, 0}; // plot co-ords of spiral into it's cache @@ -108,6 +121,8 @@ sxbp_status_t sxbp_render_spiral(sxbp_spiral_t spiral, sxbp_bitmap_t* image) { for(size_t j = i; j > 0; j--) { free(image->pixels[j]); } + // now we need to free() the top-level array + free(image->pixels); result.location = SXBP_DEBUG; result.diagnostic = SXBP_MALLOC_REFUSED; return result; diff --git a/saxbospiral/render.h b/saxbospiral/render.h index 8b422eb..34d5673 100644 --- a/saxbospiral/render.h +++ b/saxbospiral/render.h @@ -43,6 +43,10 @@ typedef struct sxbp_bitmap_t { * given a spiral struct and a pointer to a blank bitmap_t struct, writes data * representing a monochromatic image of the rendered spiral to the bitmap * returns a status struct with error information (if any) + * + * Asserts: + * - That image->pixels is NULL + * - That spiral.lines is not NULL */ sxbp_status_t sxbp_render_spiral(sxbp_spiral_t spiral, sxbp_bitmap_t* image); From f283cea771d9bf36c4a10e2bb674c6cc3956c31a Mon Sep 17 00:00:00 2001 From: Joshua Saxby Date: Thu, 27 Oct 2016 22:08:12 +0100 Subject: [PATCH 04/11] Add assertions to serialise unit These are currently failing in at least one of the tests --- saxbospiral/serialise.c | 51 +++++++++++++++++++++++++++++++++++++---- saxbospiral/serialise.h | 8 +++++++ 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/saxbospiral/serialise.c b/saxbospiral/serialise.c index e01a6ec..dfdd1bd 100644 --- a/saxbospiral/serialise.c +++ b/saxbospiral/serialise.c @@ -21,6 +21,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ +#include #include #include #include @@ -38,8 +39,15 @@ extern "C"{ const size_t SXBP_FILE_HEADER_SIZE = 37; const size_t SXBP_LINE_T_PACK_SIZE = 4; -// loads a 64-bit unsigned integer from buffer starting at given index +/* + * loads a 64-bit unsigned integer from buffer starting at given index + * + * Asserts: + * - That buffer->bytes is not NULL + */ static uint64_t load_uint64_t(sxbp_buffer_t* buffer, size_t start_index) { + // preconditional assertions + assert(buffer->bytes != NULL); uint64_t value = 0; for(size_t i = 0; i < 8; i++) { value |= (buffer->bytes[start_index + i]) << (8 * (7 - i)); @@ -47,8 +55,15 @@ static uint64_t load_uint64_t(sxbp_buffer_t* buffer, size_t start_index) { return value; } -// loads a 32-bit unsigned integer from buffer starting at given index +/* + * loads a 32-bit unsigned integer from buffer starting at given index + * + * Asserts: + * - That buffer->bytes is not NULL + */ static uint32_t load_uint32_t(sxbp_buffer_t* buffer, size_t start_index) { + // preconditional assertions + assert(buffer->bytes != NULL); uint32_t value = 0; for(size_t i = 0; i < 4; i++) { value |= (buffer->bytes[start_index + i]) << (8 * (3 - i)); @@ -56,10 +71,17 @@ static uint32_t load_uint32_t(sxbp_buffer_t* buffer, size_t start_index) { return value; } -// dumps a 64-bit unsigned integer of value to buffer at given index +/* + * dumps a 64-bit unsigned integer of value to buffer at given index + * + * Asserts: + * - That buffer->bytes is not NULL + */ static void dump_uint64_t( uint64_t value, sxbp_buffer_t* buffer, size_t start_index ) { + // preconditional assertions + assert(buffer->bytes != NULL); for(uint8_t i = 0; i < 8; i++) { uint8_t shift = (8 * (7 - i)); buffer->bytes[start_index + i] = (uint8_t)( @@ -68,10 +90,17 @@ static void dump_uint64_t( } } -// dumps a 32-bit unsigned integer of value to buffer at given index +/* + * dumps a 32-bit unsigned integer of value to buffer at given index + * + * Asserts: + * - That buffer->bytes is not NULL + */ static void dump_uint32_t( uint32_t value, sxbp_buffer_t* buffer, size_t start_index ) { + // preconditional assertions + assert(buffer->bytes != NULL); for(uint8_t i = 0; i < 4; i++) { uint8_t shift = (8 * (3 - i)); buffer->bytes[start_index + i] = (uint8_t)( @@ -86,10 +115,17 @@ static void dump_uint32_t( * returns a serialise_result_t struct, which will contain information about * whether the operation was successful or not and information about what went * wrong if it was not successful + * + * Asserts: + * - That buffer.bytes is not NULL + * - That spiral->lines is NULL */ sxbp_serialise_result_t sxbp_load_spiral( sxbp_buffer_t buffer, sxbp_spiral_t* spiral ) { + // preconditional assertions + assert(buffer.bytes != NULL); + assert(spiral->lines == NULL); sxbp_serialise_result_t result; // build struct for returning success / failure // first, if header is too small for header + 1 line, then return early if(buffer.size < SXBP_FILE_HEADER_SIZE + SXBP_LINE_T_PACK_SIZE) { @@ -177,10 +213,17 @@ sxbp_serialise_result_t sxbp_load_spiral( * returns a serialise_result_t struct, which will contain information about * whether the operation was successful or not and information about what went * wrong if it was not successful + * + * Asserts: + * - That spiral.lines is not NULL + * - That buffer->bytes is NULL */ sxbp_serialise_result_t sxbp_dump_spiral( sxbp_spiral_t spiral, sxbp_buffer_t* buffer ) { + // preconditional assertions + assert(buffer->bytes == NULL); + assert(spiral.lines != NULL); sxbp_serialise_result_t result; // build struct for returning success / failure // populate buffer struct, base size on header + spiral size buffer->size = (SXBP_FILE_HEADER_SIZE + (SXBP_LINE_T_PACK_SIZE * spiral.size)); diff --git a/saxbospiral/serialise.h b/saxbospiral/serialise.h index ec63446..fec8841 100644 --- a/saxbospiral/serialise.h +++ b/saxbospiral/serialise.h @@ -61,6 +61,10 @@ extern const size_t SXBP_LINE_T_PACK_SIZE; * returns a serialise_result_t struct, which will contain information about * whether the operation was successful or not and information about what went * wrong if it was not successful + * + * Asserts: + * - That buffer.bytes is not NULL + * - That spiral->lines is NULL */ sxbp_serialise_result_t sxbp_load_spiral( sxbp_buffer_t buffer, sxbp_spiral_t* spiral @@ -72,6 +76,10 @@ sxbp_serialise_result_t sxbp_load_spiral( * returns a serialise_result_t struct, which will contain information about * whether the operation was successful or not and information about what went * wrong if it was not successful + * + * Asserts: + * - That spiral.lines is not NULL + * - That buffer->bytes is NULL */ sxbp_serialise_result_t sxbp_dump_spiral( sxbp_spiral_t spiral, sxbp_buffer_t* buffer From 5b115d9c25b48181e34b2bb189bca26767cda34a Mon Sep 17 00:00:00 2001 From: Joshua Saxby Date: Thu, 27 Oct 2016 22:11:54 +0100 Subject: [PATCH 05/11] Fix assertions added in previous commit by amending tests --- tests.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests.c b/tests.c index c6ef30a..1c80e15 100644 --- a/tests.c +++ b/tests.c @@ -443,7 +443,7 @@ bool test_sxbp_load_spiral_rejects_missing_magic_number() { ); // call load_spiral with buffer and blank spiral, store result - sxbp_spiral_t output; + sxbp_spiral_t output = sxbp_blank_spiral(); sxbp_serialise_result_t serialise_result = sxbp_load_spiral(buffer, &output); if( @@ -466,7 +466,7 @@ bool test_sxbp_load_spiral_rejects_too_small_for_header() { buffer.bytes = (uint8_t*)"SAXBOSPIRAL"; // call load_spiral with buffer and blank spiral, store result - sxbp_spiral_t output; + sxbp_spiral_t output = sxbp_blank_spiral(); sxbp_serialise_result_t serialise_result = sxbp_load_spiral(buffer, &output); if( @@ -506,7 +506,7 @@ bool test_sxbp_load_spiral_rejects_too_small_data_section() { buffer.bytes[i+25] = data[i]; } // call load_spiral with buffer and blank spiral, store result - sxbp_spiral_t output; + sxbp_spiral_t output = sxbp_blank_spiral(); sxbp_serialise_result_t serialise_result = sxbp_load_spiral(buffer, &output); if( @@ -546,7 +546,7 @@ bool test_sxbp_load_spiral_rejects_wrong_version() { buffer.bytes[i+25] = data[i]; } // call load_spiral with buffer and blank spiral, store result - sxbp_spiral_t output; + sxbp_spiral_t output = sxbp_blank_spiral(); sxbp_serialise_result_t serialise_result = sxbp_load_spiral(buffer, &output); if( @@ -617,7 +617,7 @@ bool test_sxbp_dump_spiral() { } // call dump_spiral with spiral and write to output buffer - sxbp_buffer_t output; + sxbp_buffer_t output = { .size = 0, .bytes = NULL, }; sxbp_dump_spiral(input, &output); if(output.size != expected.size) { From 14b92b0166730c6fe8261b08c9d7d13313069576 Mon Sep 17 00:00:00 2001 From: Joshua Saxby Date: Thu, 27 Oct 2016 22:28:38 +0100 Subject: [PATCH 06/11] Added assertions to solve unit --- saxbospiral/solve.c | 31 +++++++++++++++++++++++++++++++ saxbospiral/solve.h | 7 +++++++ 2 files changed, 38 insertions(+) diff --git a/saxbospiral/solve.c b/saxbospiral/solve.c index a260e58..bfafd55 100644 --- a/saxbospiral/solve.c +++ b/saxbospiral/solve.c @@ -22,6 +22,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ +#include #include #include #include @@ -46,8 +47,17 @@ extern "C"{ * Returns boolean on whether or not the spiral collides or not. Also, sets the * collider field in the spiral struct to the index of the colliding line * (if any) + * + * Asserts: + * - That spiral->lines is not NULL + * - That spiral->co_ord_cache.co_ords.items is not NULL + * - That index is less than spiral->size */ static bool spiral_collides(sxbp_spiral_t* spiral, size_t index) { + // preconditional assertions + assert(spiral->lines != NULL); + assert(spiral->co_ord_cache.co_ords.items != NULL); + assert(index < spiral->size); /* * if there are less than 4 lines in the spiral, then there's no way it * can collide, so return false early @@ -115,10 +125,19 @@ static bool spiral_collides(sxbp_spiral_t* spiral, size_t index) { * NOTE: In the context of this function, 'rigid' or 'r' refers to the line that * the newly plotted line has collided with and 'previous' or 'p' refers to the * line before the newly plotted line. + * + * Asserts: + * - That spiral.lines is not NULL + * - That spiral.co_ord_cache.co_ords.items is not NULL + * - That index is less than spiral.size */ static sxbp_length_t suggest_resize( sxbp_spiral_t spiral, size_t index, int perfection_threshold ) { + // preconditional assertions + assert(spiral.lines != NULL); + assert(spiral.co_ord_cache.co_ords.items != NULL); + assert(index < spiral.size); // check if collides or not, return same size if no collision if(spiral.collides) { /* @@ -194,11 +213,18 @@ static sxbp_length_t suggest_resize( * aggressive optimisation) attempt to set the target line to that length, * back-tracking to resize the previous line if it collides. * returns a status struct (used for error information) + * + * Asserts: + * - That spiral->lines is not NULL + * - That index is less than spiral->size */ sxbp_status_t sxbp_resize_spiral( sxbp_spiral_t* spiral, uint64_t index, sxbp_length_t length, int perfection_threshold ) { + // preconditional assertions + assert(spiral->lines != NULL); + assert(index < spiral->size); /* * setup state variables, these are used in place of recursion for managing * state of which line is being resized, and what size it should be. @@ -273,6 +299,9 @@ sxbp_status_t sxbp_resize_spiral( * highest line that will be solved and a void pointer used for accessing the * user data. * returns a status struct (used for error information) + * + * Asserts: + * - That spiral->lines is not NULL */ sxbp_status_t sxbp_plot_spiral( sxbp_spiral_t* spiral, int perfection_threshold, uint64_t max_line, @@ -282,6 +311,8 @@ sxbp_status_t sxbp_plot_spiral( ), void* progress_callback_user_data ) { + // preconditional assertions + assert(spiral->lines != NULL); // set up result status sxbp_status_t result = {{0, 0, 0}, 0}; // get index of highest line to plot diff --git a/saxbospiral/solve.h b/saxbospiral/solve.h index 5d3046d..0c8799b 100644 --- a/saxbospiral/solve.h +++ b/saxbospiral/solve.h @@ -41,6 +41,10 @@ extern "C"{ * aggressive optimisation) attempt to set the target line to that length, * back-tracking to resize the previous line if it collides. * returns a status struct (used for error information) + * + * Asserts: + * - That spiral->lines is not NULL + * - That index is less than spiral->size */ sxbp_status_t sxbp_resize_spiral( sxbp_spiral_t* spiral, uint64_t index, sxbp_length_t length, @@ -65,6 +69,9 @@ sxbp_status_t sxbp_resize_spiral( * highest line that will be solved and a void pointer used for accessing the * user data. * returns a status struct (used for error information) + * + * Asserts: + * - That spiral->lines is not NULL */ sxbp_status_t sxbp_plot_spiral( sxbp_spiral_t* spiral, int perfection_threshold, uint64_t max_line, From fa6a0262a0749271b07a548f4037afb51b3eb457 Mon Sep 17 00:00:00 2001 From: Joshua Saxby Date: Thu, 27 Oct 2016 22:34:50 +0100 Subject: [PATCH 07/11] add fix to missed-out test case (make sure spiral is blank) --- tests.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests.c b/tests.c index 1c80e15..294c953 100644 --- a/tests.c +++ b/tests.c @@ -403,7 +403,7 @@ bool test_sxbp_load_spiral() { } // call load_spiral with buffer and write to output spiral - sxbp_spiral_t output; + sxbp_spiral_t output = sxbp_blank_spiral(); sxbp_load_spiral(buffer, &output); if(output.size != expected.size) { From 98698d07d4148a8883ec2465cc207a9a863900f3 Mon Sep 17 00:00:00 2001 From: Joshua Saxby Date: Fri, 28 Oct 2016 21:06:30 +0100 Subject: [PATCH 08/11] Remove SXBP_DEBUG macro Fixes #116 --- saxbospiral/initialise.c | 5 ++--- saxbospiral/plot.c | 16 +++++++--------- saxbospiral/render.c | 10 ++++------ saxbospiral/render_backends/png_backend.c | 11 ++++------- saxbospiral/saxbospiral.h | 21 +-------------------- saxbospiral/serialise.c | 22 ++++++++-------------- saxbospiral/solve.c | 12 ++++++------ tests.c | 8 ++++---- 8 files changed, 36 insertions(+), 69 deletions(-) diff --git a/saxbospiral/initialise.c b/saxbospiral/initialise.c index d6bae7b..2b9bfbf 100644 --- a/saxbospiral/initialise.c +++ b/saxbospiral/initialise.c @@ -74,8 +74,7 @@ sxbp_status_t sxbp_init_spiral(sxbp_buffer_t buffer, sxbp_spiral_t* spiral) { spiral->lines = calloc(sizeof(sxbp_line_t), line_count); // check for memory allocation failure if(spiral->lines == NULL) { - result.location = SXBP_DEBUG; - result.diagnostic = SXBP_MALLOC_REFUSED; + result = SXBP_MALLOC_REFUSED; return result; } // First line is always an UP line - this is for orientation purposes @@ -105,7 +104,7 @@ sxbp_status_t sxbp_init_spiral(sxbp_buffer_t buffer, sxbp_spiral_t* spiral) { } } // all ok - result.diagnostic = SXBP_OPERATION_OK; + result = SXBP_OPERATION_OK; return result; } diff --git a/saxbospiral/plot.c b/saxbospiral/plot.c index 40030af..fd92186 100644 --- a/saxbospiral/plot.c +++ b/saxbospiral/plot.c @@ -76,7 +76,7 @@ sxbp_status_t sxbp_spiral_points( assert(end <= spiral.size); assert(spiral.lines != NULL); // prepare result status - sxbp_status_t result = {{0, 0, 0}, 0}; + sxbp_status_t result; // the amount of space needed is the sum of all line lengths + 1 for end size_t size = sxbp_sum_lines(spiral, start, end) + 1; // allocate memory @@ -84,8 +84,7 @@ sxbp_status_t sxbp_spiral_points( // catch malloc error if(output->items == NULL) { // set error information then early return - result.location = SXBP_DEBUG; - result.diagnostic = SXBP_MALLOC_REFUSED; + result = SXBP_MALLOC_REFUSED; return result; } output->size = size; @@ -107,7 +106,7 @@ sxbp_status_t sxbp_spiral_points( } } // all good - result.diagnostic = SXBP_OPERATION_OK; + result = SXBP_OPERATION_OK; return result; } @@ -129,7 +128,7 @@ sxbp_status_t sxbp_cache_spiral_points(sxbp_spiral_t* spiral, size_t limit) { assert(spiral->lines != NULL); assert(limit <= spiral->size); // prepare result status - sxbp_status_t result = {{0, 0, 0}, 0}; + sxbp_status_t result; // the amount of space needed is the sum of all line lengths + 1 for end size_t size = sxbp_sum_lines(*spiral, 0, limit) + 1; // allocate / reallocate memory @@ -150,8 +149,7 @@ sxbp_status_t sxbp_cache_spiral_points(sxbp_spiral_t* spiral, size_t limit) { // catch malloc failure if(spiral->co_ord_cache.co_ords.items == NULL) { // set error information then early return - result.location = SXBP_DEBUG; - result.diagnostic = SXBP_MALLOC_REFUSED; + result = SXBP_MALLOC_REFUSED; return result; } spiral->co_ord_cache.co_ords.size = size; @@ -180,7 +178,7 @@ sxbp_status_t sxbp_cache_spiral_points(sxbp_spiral_t* spiral, size_t limit) { *spiral, &missing, current, smallest, limit ); // return errors from previous call if needed - if(calculate_result.diagnostic != SXBP_OPERATION_OK) { + if(calculate_result != SXBP_OPERATION_OK) { return calculate_result; } // add the missing co-ords to the cache @@ -196,7 +194,7 @@ sxbp_status_t sxbp_cache_spiral_points(sxbp_spiral_t* spiral, size_t limit) { limit > spiral->co_ord_cache.validity ) ? limit : spiral->co_ord_cache.validity; // return ok - result.diagnostic = SXBP_OPERATION_OK; + result = SXBP_OPERATION_OK; return result; } diff --git a/saxbospiral/render.c b/saxbospiral/render.c index 55808b2..e6b5c46 100644 --- a/saxbospiral/render.c +++ b/saxbospiral/render.c @@ -86,7 +86,7 @@ sxbp_status_t sxbp_render_spiral(sxbp_spiral_t spiral, sxbp_bitmap_t* image) { assert(image->pixels == NULL); assert(spiral.lines != NULL); // create result status struct - sxbp_status_t result = {{0, 0, 0}, 0}; + sxbp_status_t result; // plot co-ords of spiral into it's cache sxbp_cache_spiral_points(&spiral, spiral.size); // get the min and max bounds of the spiral's co-ords @@ -109,8 +109,7 @@ sxbp_status_t sxbp_render_spiral(sxbp_spiral_t spiral, sxbp_bitmap_t* image) { image->pixels = malloc(image->width * sizeof(bool*)); // check for malloc fail if(image->pixels == NULL) { - result.location = SXBP_DEBUG; - result.diagnostic = SXBP_MALLOC_REFUSED; + result = SXBP_MALLOC_REFUSED; return result; } for(size_t i = 0; i < image->width; i++) { @@ -123,8 +122,7 @@ sxbp_status_t sxbp_render_spiral(sxbp_spiral_t spiral, sxbp_bitmap_t* image) { } // now we need to free() the top-level array free(image->pixels); - result.location = SXBP_DEBUG; - result.diagnostic = SXBP_MALLOC_REFUSED; + result = SXBP_MALLOC_REFUSED; return result; } } @@ -155,7 +153,7 @@ sxbp_status_t sxbp_render_spiral(sxbp_spiral_t spiral, sxbp_bitmap_t* image) { } } // status ok - result.diagnostic = SXBP_OPERATION_OK; + result = SXBP_OPERATION_OK; return result; } diff --git a/saxbospiral/render_backends/png_backend.c b/saxbospiral/render_backends/png_backend.c index 45bd03a..b4fb08e 100644 --- a/saxbospiral/render_backends/png_backend.c +++ b/saxbospiral/render_backends/png_backend.c @@ -99,8 +99,7 @@ sxbp_status_t sxbp_write_png_image( png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); // catch malloc fail if(png_ptr == NULL) { - result.location = SXBP_DEBUG; - result.diagnostic = SXBP_MALLOC_REFUSED; + result = SXBP_MALLOC_REFUSED; // cleanup cleanup_png_lib(png_ptr, info_ptr, row); return result; @@ -109,8 +108,7 @@ sxbp_status_t sxbp_write_png_image( info_ptr = png_create_info_struct(png_ptr); // catch malloc fail if(info_ptr == NULL) { - result.location = SXBP_DEBUG; - result.diagnostic = SXBP_MALLOC_REFUSED; + result = SXBP_MALLOC_REFUSED; // cleanup cleanup_png_lib(png_ptr, info_ptr, row); return result; @@ -159,8 +157,7 @@ sxbp_status_t sxbp_write_png_image( row = (png_bytep) malloc(bitmap.width * sizeof(png_byte)); // catch malloc fail if(row == NULL) { - result.location = SXBP_DEBUG; - result.diagnostic = SXBP_MALLOC_REFUSED; + result = SXBP_MALLOC_REFUSED; // cleanup cleanup_png_lib(png_ptr, info_ptr, row); return result; @@ -178,7 +175,7 @@ sxbp_status_t sxbp_write_png_image( // cleanup cleanup_png_lib(png_ptr, info_ptr, row); // status ok - result.diagnostic = SXBP_OPERATION_OK; + result = SXBP_OPERATION_OK; return result; } diff --git a/saxbospiral/saxbospiral.h b/saxbospiral/saxbospiral.h index 54cc8aa..670ed32 100644 --- a/saxbospiral/saxbospiral.h +++ b/saxbospiral/saxbospiral.h @@ -51,32 +51,13 @@ typedef uint32_t sxbp_version_hash_t; */ sxbp_version_hash_t sxbp_version_hash(sxbp_version_t version); -// struct for storing the location of a DEBUG invocation -typedef struct sxbp_debug_t { - size_t line; - char* file; - const char* function; -} sxbp_debug_t; - -/* - * handy short-hand for debugging purposes - * usage: debug_t debug = DEBUG; - */ -#define SXBP_DEBUG (sxbp_debug_t) { .line = __LINE__, .file = __FILE__, .function = __func__, } - // enum for function error information -typedef enum sxbp_diagnostic_t { +typedef enum sxbp_status_t { SXBP_STATE_UNKNOWN = 0, // unknown, the default state SXBP_OPERATION_FAIL, // generic failure state SXBP_MALLOC_REFUSED, // memory allocation or re-allocation was refused SXBP_IMPOSSIBLE_CONDITION, // condition thought to be impossible detected SXBP_OPERATION_OK, // no problem -} sxbp_diagnostic_t; - -// struct for storing generic diagnostics about function failure reasons -typedef struct sxbp_status_t { - sxbp_debug_t location; // for storing location of error - sxbp_diagnostic_t diagnostic; // for storing error information (if any) } sxbp_status_t; // type for representing a cartesian direction diff --git a/saxbospiral/serialise.c b/saxbospiral/serialise.c index dfdd1bd..069817e 100644 --- a/saxbospiral/serialise.c +++ b/saxbospiral/serialise.c @@ -129,15 +129,13 @@ sxbp_serialise_result_t sxbp_load_spiral( sxbp_serialise_result_t result; // build struct for returning success / failure // first, if header is too small for header + 1 line, then return early if(buffer.size < SXBP_FILE_HEADER_SIZE + SXBP_LINE_T_PACK_SIZE) { - result.status.location = SXBP_DEBUG; // catch location of error - result.status.diagnostic = SXBP_OPERATION_FAIL; // flag failure + result.status = SXBP_OPERATION_FAIL; // flag failure result.diagnostic = SXBP_DESERIALISE_BAD_HEADER_SIZE; // failure reason return result; } // check for magic number and return early if not right if(strncmp((char*)buffer.bytes, "SAXBOSPIRAL", 11) != 0) { - result.status.location = SXBP_DEBUG; // catch location of error - result.status.diagnostic = SXBP_OPERATION_FAIL; // flag failure + result.status = SXBP_OPERATION_FAIL; // flag failure result.diagnostic = SXBP_DESERIALISE_BAD_MAGIC_NUMBER; // failure reason return result; } @@ -152,8 +150,7 @@ sxbp_serialise_result_t sxbp_load_spiral( // check for version compatibility if(sxbp_version_hash(buffer_version) < sxbp_version_hash(min_version)) { // check failed - result.status.location = SXBP_DEBUG; // catch location of error - result.status.diagnostic = SXBP_OPERATION_FAIL; // flag failure + result.status = SXBP_OPERATION_FAIL; // flag failure result.diagnostic = SXBP_DESERIALISE_BAD_VERSION; // failure reason return result; } @@ -162,8 +159,7 @@ sxbp_serialise_result_t sxbp_load_spiral( // Check that the file data section is large enough for the spiral size if((buffer.size - SXBP_FILE_HEADER_SIZE) != (SXBP_LINE_T_PACK_SIZE * spiral_size)) { // this check failed - result.status.location = SXBP_DEBUG; // catch location of error - result.status.diagnostic = SXBP_OPERATION_FAIL; // flag failure + result.status = SXBP_OPERATION_FAIL; // flag failure result.diagnostic = SXBP_DESERIALISE_BAD_DATA_SIZE; // failure reason return result; } @@ -176,8 +172,7 @@ sxbp_serialise_result_t sxbp_load_spiral( spiral->lines = calloc(sizeof(sxbp_line_t), spiral->size); // catch allocation error if(spiral->lines == NULL) { - result.status.location = SXBP_DEBUG; // catch location of error - result.status.diagnostic = SXBP_MALLOC_REFUSED; // flag failure + result.status = SXBP_MALLOC_REFUSED; // flag failure return result; } // convert each serialised line segment in buffer into a line_t struct @@ -203,7 +198,7 @@ sxbp_serialise_result_t sxbp_load_spiral( } } // return ok status - result.status.diagnostic = SXBP_OPERATION_OK; + result.status = SXBP_OPERATION_OK; return result; } @@ -231,8 +226,7 @@ sxbp_serialise_result_t sxbp_dump_spiral( buffer->bytes = calloc(1, buffer->size); // catch memory allocation failure if(buffer->bytes == NULL) { - result.status.location = SXBP_DEBUG; - result.status.diagnostic = SXBP_MALLOC_REFUSED; + result.status = SXBP_MALLOC_REFUSED; return result; } // write first part of data header (magic number and version info) @@ -267,7 +261,7 @@ sxbp_serialise_result_t sxbp_dump_spiral( } } // return ok status - result.status.diagnostic = SXBP_OPERATION_OK; + result.status = SXBP_OPERATION_OK; return result; } diff --git a/saxbospiral/solve.c b/saxbospiral/solve.c index bfafd55..0f27568 100644 --- a/saxbospiral/solve.c +++ b/saxbospiral/solve.c @@ -230,7 +230,7 @@ sxbp_status_t sxbp_resize_spiral( * state of which line is being resized, and what size it should be. */ // set result status - sxbp_status_t result = {{0, 0, 0}, 0}; + sxbp_status_t result; size_t current_index = index; sxbp_length_t current_length = length; while(true) { @@ -246,7 +246,7 @@ sxbp_status_t sxbp_resize_spiral( // update the spiral's co-ord cache, and catch any errors result = sxbp_cache_spiral_points(spiral, current_index + 1); // return if errors - if(result.diagnostic != SXBP_OPERATION_OK) { + if(result != SXBP_OPERATION_OK) { return result; } spiral->collides = spiral_collides(spiral, current_index); @@ -275,7 +275,7 @@ sxbp_status_t sxbp_resize_spiral( * Return OPERATION_OK from function. */ spiral->solved_count = index + 1; - result.diagnostic = SXBP_OPERATION_OK; + result = SXBP_OPERATION_OK; return result; } } @@ -314,14 +314,14 @@ sxbp_status_t sxbp_plot_spiral( // preconditional assertions assert(spiral->lines != NULL); // set up result status - sxbp_status_t result = {{0, 0, 0}, 0}; + sxbp_status_t result; // get index of highest line to plot uint64_t max_index = (max_line > spiral->size) ? spiral->size : max_line; // calculate the length of each line within range solved_count -> max_index for(size_t i = spiral->solved_count; i < max_index; i++) { result = sxbp_resize_spiral(spiral, i, 1, perfection_threshold); // catch and return error if any - if(result.diagnostic != SXBP_OPERATION_OK) { + if(result != SXBP_OPERATION_OK) { return result; } // call callback if given @@ -330,7 +330,7 @@ sxbp_status_t sxbp_plot_spiral( } } // all ok - result.diagnostic = SXBP_OPERATION_OK; + result = SXBP_OPERATION_OK; return result; } diff --git a/tests.c b/tests.c index 294c953..78f761c 100644 --- a/tests.c +++ b/tests.c @@ -447,7 +447,7 @@ bool test_sxbp_load_spiral_rejects_missing_magic_number() { sxbp_serialise_result_t serialise_result = sxbp_load_spiral(buffer, &output); if( - (serialise_result.status.diagnostic != SXBP_OPERATION_FAIL) || + (serialise_result.status != SXBP_OPERATION_FAIL) || (serialise_result.diagnostic != SXBP_DESERIALISE_BAD_MAGIC_NUMBER) ) { result = false; @@ -470,7 +470,7 @@ bool test_sxbp_load_spiral_rejects_too_small_for_header() { sxbp_serialise_result_t serialise_result = sxbp_load_spiral(buffer, &output); if( - (serialise_result.status.diagnostic != SXBP_OPERATION_FAIL) || + (serialise_result.status != SXBP_OPERATION_FAIL) || (serialise_result.diagnostic != SXBP_DESERIALISE_BAD_HEADER_SIZE) ) { result = false; @@ -510,7 +510,7 @@ bool test_sxbp_load_spiral_rejects_too_small_data_section() { sxbp_serialise_result_t serialise_result = sxbp_load_spiral(buffer, &output); if( - (serialise_result.status.diagnostic != SXBP_OPERATION_FAIL) || + (serialise_result.status != SXBP_OPERATION_FAIL) || (serialise_result.diagnostic != SXBP_DESERIALISE_BAD_DATA_SIZE) ) { result = false; @@ -550,7 +550,7 @@ bool test_sxbp_load_spiral_rejects_wrong_version() { sxbp_serialise_result_t serialise_result = sxbp_load_spiral(buffer, &output); if( - (serialise_result.status.diagnostic != SXBP_OPERATION_FAIL) || + (serialise_result.status != SXBP_OPERATION_FAIL) || (serialise_result.diagnostic != SXBP_DESERIALISE_BAD_VERSION) ) { result = false; From 83e50f4008fdbff653c63d2021f5df358b12ea8d Mon Sep 17 00:00:00 2001 From: Joshua Saxby Date: Fri, 28 Oct 2016 21:39:50 +0100 Subject: [PATCH 09/11] Update CMake script to install headers to version-dependent place Also, improved the warning message given if we suspect the target does not support at least 64-bit's worth of integers. --- CMakeLists.txt | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 75b33cb..b8cadcc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,7 +50,9 @@ if(CMAKE_SIZEOF_VOID_P LESS 8) message( WARNING "It looks like this system's architecture is not at least 64-bit.\n" - "libsaxbospiral requires a system with an architecture of at least 64 bits!") + "libsaxbospiral requires a system with an architecture of at least 64 bits!\n" + "We'll continue trying to compile anyway, be sure to run the unit tests after." + ) endif() # pass in version of library as preprocessor definitions @@ -123,15 +125,22 @@ install( LIBRARY DESTINATION lib RUNTIME DESTINATION bin ) + +# Generate version-dependent header installation folder +set( + LIBSAXBOSPIRAL_HEADER_DESTINATION + "saxbospiral-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}" +) + # Install main library header files install( FILES ${LIB_SAXBOSPIRAL_HEADERS} - DESTINATION include/saxbospiral + DESTINATION "include/${LIBSAXBOSPIRAL_HEADER_DESTINATION}" ) # Install render_backends header files install( FILES ${LIB_SAXBOSPIRAL_RENDER_BACKENDS_HEADERS} - DESTINATION include/saxbospiral/render_backends + DESTINATION "include/${LIBSAXBOSPIRAL_HEADER_DESTINATION}/render_backends" ) enable_testing() From d50cb2f79899074dd5908a17512bb492257e1062 Mon Sep 17 00:00:00 2001 From: Joshua Saxby Date: Fri, 28 Oct 2016 21:45:26 +0100 Subject: [PATCH 10/11] Install to locations based on major and major.minor versions --- CMakeLists.txt | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b8cadcc..cd29952 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -126,21 +126,36 @@ install( RUNTIME DESTINATION bin ) -# Generate version-dependent header installation folder +# Generate rough (nearest major) version-dependent header installation folder set( - LIBSAXBOSPIRAL_HEADER_DESTINATION + LIBSAXBOSPIRAL_ROUGH_HEADER_DESTINATION + "saxbospiral-${PROJECT_VERSION_MAJOR}" +) +# Generate precise (major and minor) version-dependent header installation folder +set( + LIBSAXBOSPIRAL_PRECISE_HEADER_DESTINATION "saxbospiral-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}" ) -# Install main library header files +# Install main library header files, both to rough and precise install locations +install( + FILES ${LIB_SAXBOSPIRAL_HEADERS} + DESTINATION "include/${LIBSAXBOSPIRAL_ROUGH_HEADER_DESTINATION}" +) +# Install render_backends header files +install( + FILES ${LIB_SAXBOSPIRAL_RENDER_BACKENDS_HEADERS} + DESTINATION "include/${LIBSAXBOSPIRAL_ROUGH_HEADER_DESTINATION}/render_backends" +) + install( FILES ${LIB_SAXBOSPIRAL_HEADERS} - DESTINATION "include/${LIBSAXBOSPIRAL_HEADER_DESTINATION}" + DESTINATION "include/${LIBSAXBOSPIRAL_PRECISE_HEADER_DESTINATION}" ) # Install render_backends header files install( FILES ${LIB_SAXBOSPIRAL_RENDER_BACKENDS_HEADERS} - DESTINATION "include/${LIBSAXBOSPIRAL_HEADER_DESTINATION}/render_backends" + DESTINATION "include/${LIBSAXBOSPIRAL_PRECISE_HEADER_DESTINATION}/render_backends" ) enable_testing() From 3c2c4462f9083b7fadddbebcb7987c152a13393b Mon Sep 17 00:00:00 2001 From: Joshua Saxby Date: Fri, 28 Oct 2016 21:58:36 +0100 Subject: [PATCH 11/11] Bump version due to small breaking changes (v0.20.0) --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cd29952..31994f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ # begin basic metadata cmake_minimum_required(VERSION 3.0) -project(libsaxbospiral VERSION 0.19.3 LANGUAGES C) +project(libsaxbospiral VERSION 0.20.0 LANGUAGES C) # set default C standard to use (C99) set(SAXBOSPIRAL_C_STANDARD "99")