diff --git a/CMakeLists.txt b/CMakeLists.txt
index 75b33cb..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")
@@ -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,37 @@ install(
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
)
-# Install main library header files
+
+# Generate rough (nearest major) version-dependent header installation folder
+set(
+ 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, 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/saxbospiral
+ DESTINATION "include/${LIBSAXBOSPIRAL_PRECISE_HEADER_DESTINATION}"
)
# Install render_backends header files
install(
FILES ${LIB_SAXBOSPIRAL_RENDER_BACKENDS_HEADERS}
- DESTINATION include/saxbospiral/render_backends
+ DESTINATION "include/${LIBSAXBOSPIRAL_PRECISE_HEADER_DESTINATION}/render_backends"
)
enable_testing()
diff --git a/saxbospiral/initialise.c b/saxbospiral/initialise.c
index 4c8abd3..2b9bfbf 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
@@ -67,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
@@ -98,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/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..fd92186 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,18 @@
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 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 <= 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;
@@ -49,13 +60,23 @@ 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};
+ 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
@@ -63,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;
@@ -86,22 +106,29 @@ sxbp_status_t sxbp_spiral_points(
}
}
// all good
- result.diagnostic = SXBP_OPERATION_OK;
+ result = SXBP_OPERATION_OK;
return result;
}
/*
- * 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};
+ 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
@@ -122,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;
@@ -152,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
@@ -168,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/plot.h b/saxbospiral/plot.h
index 0a554d4..2449f3c 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 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);
/*
@@ -45,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,
@@ -52,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/saxbospiral/render.c b/saxbospiral/render.c
index 34adf45..e6b5c46 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,10 +76,17 @@ 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};
+ 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
@@ -96,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++) {
@@ -108,8 +120,9 @@ 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]);
}
- result.location = SXBP_DEBUG;
- result.diagnostic = SXBP_MALLOC_REFUSED;
+ // now we need to free() the top-level array
+ free(image->pixels);
+ result = SXBP_MALLOC_REFUSED;
return result;
}
}
@@ -140,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.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);
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 e01a6ec..069817e 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,22 +115,27 @@ 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) {
- 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;
}
@@ -116,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;
}
@@ -126,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;
}
@@ -140,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
@@ -167,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;
}
@@ -177,10 +208,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));
@@ -188,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)
@@ -224,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/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
diff --git a/saxbospiral/solve.c b/saxbospiral/solve.c
index a260e58..0f27568 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,17 +213,24 @@ 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.
*/
// 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) {
@@ -220,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);
@@ -249,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;
}
}
@@ -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,15 +311,17 @@ 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};
+ 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
@@ -299,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/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,
diff --git a/tests.c b/tests.c
index 9650e53..78f761c 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) {
@@ -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) {
@@ -443,11 +443,11 @@ 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(
- (serialise_result.status.diagnostic != SXBP_OPERATION_FAIL) ||
+ (serialise_result.status != SXBP_OPERATION_FAIL) ||
(serialise_result.diagnostic != SXBP_DESERIALISE_BAD_MAGIC_NUMBER)
) {
result = false;
@@ -466,11 +466,11 @@ 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(
- (serialise_result.status.diagnostic != SXBP_OPERATION_FAIL) ||
+ (serialise_result.status != SXBP_OPERATION_FAIL) ||
(serialise_result.diagnostic != SXBP_DESERIALISE_BAD_HEADER_SIZE)
) {
result = false;
@@ -506,11 +506,11 @@ 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(
- (serialise_result.status.diagnostic != SXBP_OPERATION_FAIL) ||
+ (serialise_result.status != SXBP_OPERATION_FAIL) ||
(serialise_result.diagnostic != SXBP_DESERIALISE_BAD_DATA_SIZE)
) {
result = false;
@@ -546,11 +546,11 @@ 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(
- (serialise_result.status.diagnostic != SXBP_OPERATION_FAIL) ||
+ (serialise_result.status != SXBP_OPERATION_FAIL) ||
(serialise_result.diagnostic != SXBP_DESERIALISE_BAD_VERSION)
) {
result = false;
@@ -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) {