Skip to content

Commit 02fd493

Browse files
authored
Merge pull request #53 from saxbophone/develop
v0.12.0
2 parents 8fdf656 + 88c696a commit 02fd493

File tree

18 files changed

+529
-341
lines changed

18 files changed

+529
-341
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
cmake_minimum_required(VERSION 3.0)
33
enable_language(C CXX)
44

5-
project(saxbospiral VERSION 0.11.3 LANGUAGES C)
5+
project(saxbospiral VERSION 0.12.0 LANGUAGES C)
66
set(CMAKE_C_STANDARD 99)
77
set(CMAKE_C_STANDARD_REQUIRED ON)
88
set(

build_logo.sh

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,4 @@
88
#
99
echo "Generating logo";
1010
echo -n "$3" > temp.hex && \
11-
./"$1" -pg -i temp.hex -o temp.sxp && \
12-
./"$1" -r -i temp.sxp -o "$2"
13-
rm temp.hex temp.sxp;
11+
./"$1" -pgr -i temp.hex -o "$2";

saxbospiral.png

3 Bytes
Loading

saxbospiral/initialise.c

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <stdint.h>
22
#include <stdlib.h>
33

4+
#include "saxbospiral.h"
45
#include "initialise.h"
56

67

@@ -18,25 +19,33 @@ change_direction(direction_t current, rotation_t turn) {
1819
}
1920

2021
/*
21-
* initialises a spiral_t struct from an array pointer to unsigned bytes
22+
* given a buffer_t full of data, and a pointer to a blank spiral_t
23+
* struct, populates the spiral struct from the data in the buffer
2224
* this converts the 0s and 1s in the data into UP, LEFT, DOWN, RIGHT
2325
* instructions which are then used to build the pattern.
26+
* returns a status_t struct with error information (if needed)
2427
*/
25-
spiral_t
26-
init_spiral(buffer_t buffer) {
28+
status_t
29+
init_spiral(buffer_t buffer, spiral_t * spiral) {
30+
// result status object
31+
status_t result;
2732
// number of lines is number of bits of the data, + 1 for the first UP line
2833
size_t line_count = (buffer.size * 8) + 1;
29-
// create spiral_t struct
30-
spiral_t result = {
31-
.size = line_count,
32-
.collides = -1,
33-
// allocate enough memory for a line_t struct for each bit
34-
.lines = calloc(sizeof(line_t), line_count),
35-
};
34+
// populate spiral struct
35+
spiral->size = line_count;
36+
spiral->collides = -1;
37+
// allocate enough memory for a line_t struct for each bit
38+
spiral->lines = calloc(sizeof(line_t), line_count);
39+
// check for memory allocation failure
40+
if(spiral->lines == NULL) {
41+
result.location = DEBUG;
42+
result.diagnostic = MALLOC_REFUSED;
43+
return result;
44+
}
3645
// First line is always an UP line - this is for orientation purposes
3746
direction_t current = UP;
38-
result.lines[0].direction = current;
39-
result.lines[0].length = 0;
47+
spiral->lines[0].direction = current;
48+
spiral->lines[0].length = 0;
4049
/*
4150
* now, iterate over all the bits in the data and convert to directions
4251
* that make the spiral pattern, storing these directions in the result lines
@@ -54,11 +63,13 @@ init_spiral(buffer_t buffer) {
5463
// calculate the change of direction
5564
current = change_direction(current, rotation);
5665
// store direction in result struct
57-
result.lines[index].direction = current;
66+
spiral->lines[index].direction = current;
5867
// set length to 0 initially
59-
result.lines[index].length = 0;
68+
spiral->lines[index].length = 0;
6069
}
6170
}
71+
// all ok
72+
result.diagnostic = OPERATION_OK;
6273
return result;
6374
}
6475

saxbospiral/initialise.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@ direction_t
1616
change_direction(direction_t current, rotation_t turn);
1717

1818
/*
19-
* initialises a spiral_t struct from an array pointer to unsigned bytes
19+
* given a buffer_t full of data, and a pointer to a blank spiral_t
20+
* struct, populates the spiral struct from the data in the buffer
2021
* this converts the 0s and 1s in the data into UP, LEFT, DOWN, RIGHT
2122
* instructions which are then used to build the pattern.
23+
* returns a status_t struct with error information (if needed)
2224
*/
23-
spiral_t
24-
init_spiral(buffer_t buffer);
25+
status_t
26+
init_spiral(buffer_t buffer, spiral_t * spiral);
2527

2628
#ifdef __cplusplus
2729
} // extern "C"

saxbospiral/plot.c

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,28 +20,39 @@ sum_lines(spiral_t spiral, size_t start, size_t end) {
2020
}
2121

2222
/*
23-
* given a spiral_t struct, a pair of co-ords specifying the start point and
24-
* indexes of the lowest and highest line segments to use, return a
25-
* co_ord_array_t struct containing all the co-ordinates of the line segments of
26-
* the struct according to the current directions and lengths of the lines in
27-
* the spiral.
23+
* given a spiral_t struct, a pointer to a co_ord_array_t, a pair of co-ords
24+
* specifying the start point and indexes of the lowest and highest line
25+
* segments to use, write to the co_ord_array_t struct all the co-ordinates of
26+
* the line segments of the struct according to the current directions and
27+
* lengths of the lines in the spiral.
2828
* each line segment is only one unit long, meaning multiple ones are needed for
2929
* lines longer than one unit.
30+
* returns a status struct with error information (if any)
3031
*/
31-
co_ord_array_t
32-
spiral_points(spiral_t spiral, co_ord_t start_point, size_t start, size_t end) {
32+
status_t
33+
spiral_points(
34+
spiral_t spiral, co_ord_array_t * output, co_ord_t start_point,
35+
size_t start, size_t end
36+
) {
37+
// prepare result status
38+
status_t result = {};
3339
// the amount of space needed is the sum of all line lengths + 1 for end
3440
size_t size = sum_lines(spiral, start, end) + 1;
3541
// allocate memory
36-
co_ord_array_t results = {
37-
.items = calloc(sizeof(co_ord_t), size),
38-
.size = size,
39-
};
42+
output->items = calloc(sizeof(co_ord_t), size);
43+
// catch malloc error
44+
if(output->items == NULL) {
45+
// set error information then early return
46+
result.location = DEBUG;
47+
result.diagnostic = MALLOC_REFUSED;
48+
return result;
49+
}
50+
output->size = size;
4051
// start current co-ordinate at the given start point
4152
co_ord_t current = start_point;
4253
// initialise independent result index
4354
size_t result_index = 0;
44-
results.items[result_index] = current;
55+
output->items[result_index] = current;
4556
// calculate all the specified co-ords
4657
for(size_t i = start; i < end; i++) {
4758
// get current direction
@@ -50,11 +61,13 @@ spiral_points(spiral_t spiral, co_ord_t start_point, size_t start, size_t end) {
5061
for(length_t j = 0; j < spiral.lines[i].length; j++) {
5162
current.x += direction.x;
5263
current.y += direction.y;
53-
results.items[result_index + 1] = current;
64+
output->items[result_index + 1] = current;
5465
result_index++;
5566
}
5667
}
57-
return results;
68+
// all good
69+
result.diagnostic = OPERATION_OK;
70+
return result;
5871
}
5972

6073
/*
@@ -64,9 +77,12 @@ spiral_points(spiral_t spiral, co_ord_t start_point, size_t start, size_t end) {
6477
* each line segment is only one unit long, meaning multiple ones are needed for
6578
* lines longer than one unit. The co-ords are stored in the spiral's co_ord_cache
6679
* member and are re-used if they are still valid
80+
* returns a status struct with error information (if any)
6781
*/
68-
void
82+
status_t
6983
cache_spiral_points(spiral_t * spiral, size_t limit) {
84+
// prepare result status
85+
status_t result = {};
7086
// the amount of space needed is the sum of all line lengths + 1 for end
7187
size_t size = sum_lines(*spiral, 0, limit) + 1;
7288
// allocate / reallocate memory
@@ -82,6 +98,13 @@ cache_spiral_points(spiral_t * spiral, size_t limit) {
8298
spiral->co_ord_cache.co_ords.items, sizeof(co_ord_t) * size
8399
);
84100
}
101+
// catch malloc failure
102+
if(spiral->co_ord_cache.co_ords.items == NULL) {
103+
// set error information then early return
104+
result.location = DEBUG;
105+
result.diagnostic = MALLOC_REFUSED;
106+
return result;
107+
}
85108
spiral->co_ord_cache.co_ords.size = size;
86109
// start at (0, 0) as origin
87110
co_ord_t current = { 0, 0, };
@@ -103,7 +126,14 @@ cache_spiral_points(spiral_t * spiral, size_t limit) {
103126
spiral->co_ord_cache.co_ords.items[0] = current;
104127
}
105128
// calculate the missing co-ords
106-
co_ord_array_t missing = spiral_points(*spiral, current, smallest, limit);
129+
co_ord_array_t missing= {};
130+
status_t calculate_result = spiral_points(
131+
*spiral, &missing, current, smallest, limit
132+
);
133+
// return errors from previous call if needed
134+
if(calculate_result.diagnostic != OPERATION_OK) {
135+
return calculate_result;
136+
}
107137
// add the missing co-ords to the cache
108138
for(size_t i = result_index; i < size; i++) {
109139
spiral->co_ord_cache.co_ords.items[i] = missing.items[i-result_index];
@@ -116,6 +146,9 @@ cache_spiral_points(spiral_t * spiral, size_t limit) {
116146
spiral->co_ord_cache.validity = (
117147
limit > spiral->co_ord_cache.validity
118148
) ? limit : spiral->co_ord_cache.validity;
149+
// return ok
150+
result.diagnostic = OPERATION_OK;
151+
return result;
119152
}
120153

121154
#ifdef __cplusplus

saxbospiral/plot.h

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,20 @@ size_t
1515
sum_lines(spiral_t spiral, size_t start, size_t end);
1616

1717
/*
18-
* given a spiral_t struct, a pair of co-ords specifying the start point and
19-
* indexes of the lowest and highest line segments to use, return a
20-
* co_ord_array_t struct containing all the co-ordinates of the line segments of
21-
* the struct according to the current directions and lengths of the lines in
22-
* the spiral.
18+
* given a spiral_t struct, a pointer to a co_ord_array_t, a pair of co-ords
19+
* specifying the start point and indexes of the lowest and highest line
20+
* segments to use, write to the co_ord_array_t struct all the co-ordinates of
21+
* the line segments of the struct according to the current directions and
22+
* lengths of the lines in the spiral.
2323
* each line segment is only one unit long, meaning multiple ones are needed for
2424
* lines longer than one unit.
25+
* returns a status struct with error information (if any)
2526
*/
26-
co_ord_array_t
27-
spiral_points(spiral_t spiral, co_ord_t start_point, size_t start, size_t end);
27+
status_t
28+
spiral_points(
29+
spiral_t spiral, co_ord_array_t * output, co_ord_t start_point,
30+
size_t start, size_t end
31+
);
2832

2933
/*
3034
* given a pointer to a spiral struct an limit, which is the index of the last
@@ -33,8 +37,9 @@ spiral_points(spiral_t spiral, co_ord_t start_point, size_t start, size_t end);
3337
* each line segment is only one unit long, meaning multiple ones are needed for
3438
* lines longer than one unit. The co-ords are stored in the spiral's co_ord_cache
3539
* member and are re-used if they are still valid
40+
* returns a status struct with error information (if any)
3641
*/
37-
void
42+
status_t
3843
cache_spiral_points(spiral_t * spiral, size_t limit);
3944

4045
#ifdef __cplusplus

saxbospiral/render.c

Lines changed: 51 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,14 @@ extern "C"{
1717
#endif
1818

1919
/*
20-
* given a spiral struct with co-ords in it's cache, find and return the co-ords
21-
* for the corners of the square needed to contain the points.
20+
* given a spiral struct with co-ords in it's cache and a pointer to a
21+
* 2-item-long array of type co_ord_t, find and store the co-ords for the
22+
* corners of the square needed to contain the points.
23+
* NOTE: This should NEVER be called with a pointer to anything other than a
24+
* 2-item struct of type co_ord_t
2225
*/
23-
static co_ord_array_t
24-
get_bounds(spiral_t spiral) {
26+
static void
27+
get_bounds(spiral_t spiral, co_ord_t * bounds) {
2528
tuple_item_t min_x = 0;
2629
tuple_item_t min_y = 0;
2730
tuple_item_t max_x = 0;
@@ -40,54 +43,64 @@ get_bounds(spiral_t spiral) {
4043
max_y = spiral.co_ord_cache.co_ords.items[i].y;
4144
}
4245
}
43-
// initialise output struct
44-
co_ord_array_t bounds = {
45-
.size = 2,
46-
.items = calloc(sizeof(co_ord_t), 2),
47-
};
4846
// write bounds to struct
49-
bounds.items[0].x = min_x;
50-
bounds.items[0].y = min_y;
51-
bounds.items[1].x = max_x;
52-
bounds.items[1].y = max_y;
53-
return bounds;
47+
bounds[0].x = min_x;
48+
bounds[0].y = min_y;
49+
bounds[1].x = max_x;
50+
bounds[1].y = max_y;
5451
}
5552

5653
/*
57-
* given a spiral struct, returns a bitmap_t representing a monochromatic image
58-
* of the rendered spiral
54+
* given a spiral struct and a pointer to a blank bitmap_t struct, writes data
55+
* representing a monochromatic image of the rendered spiral to the bitmap
56+
* returns a status struct with error information (if any)
5957
*/
60-
bitmap_t
61-
render_spiral(spiral_t spiral) {
58+
status_t
59+
render_spiral(spiral_t spiral, bitmap_t * image) {
60+
// create result status struct
61+
status_t result = {};
6262
// plot co-ords of spiral into it's cache
6363
cache_spiral_points(&spiral, spiral.size);
6464
// get the min and max bounds of the spiral's co-ords
65-
co_ord_array_t bounds = get_bounds(spiral);
65+
co_ord_t bounds[2] = {};
66+
get_bounds(spiral, bounds);
6667
// get the normalisation vector needed to make all values unsigned
6768
tuple_t normalisation_vector = {
68-
.x = -bounds.items[0].x,
69-
.y = -bounds.items[0].y,
69+
.x = -bounds[0].x,
70+
.y = -bounds[0].y,
7071
};
7172
// get co-ords of top left and bottom right corners, as unsigned
7273
co_ord_t top_left = {
7374
.x = 0,
7475
.y = 0,
7576
};
7677
co_ord_t bottom_right = {
77-
.x = bounds.items[1].x + normalisation_vector.x,
78-
.y = bounds.items[1].y + normalisation_vector.y,
79-
};
80-
// free memory allocated for bounds.items, as we no longer need it
81-
free(bounds.items);
82-
// initialise output bitmap - image dimensions are twice the size + 1
83-
bitmap_t output = {
84-
.width = ((bottom_right.x + 1) * 2) + 1,
85-
.height = ((bottom_right.y + 1) * 2) + 1,
78+
.x = bounds[1].x + normalisation_vector.x,
79+
.y = bounds[1].y + normalisation_vector.y,
8680
};
87-
// allocate dynamic memory - 2D array of bools
88-
output.pixels = malloc(output.width * sizeof(bool*));
89-
for(size_t i = 0; i < output.width; i++) {
90-
output.pixels[i] = calloc(output.height, sizeof(bool));
81+
// initialise image struct - image dimensions are twice the size + 1
82+
image->width = ((bottom_right.x + 1) * 2) + 1;
83+
image->height = ((bottom_right.y + 1) * 2) + 1;
84+
// allocate dynamic memory to image struct - 2D array of bools
85+
image->pixels = malloc(image->width * sizeof(bool*));
86+
// check for malloc fail
87+
if(image->pixels == NULL) {
88+
result.location = DEBUG;
89+
result.diagnostic = MALLOC_REFUSED;
90+
return result;
91+
}
92+
for(size_t i = 0; i < image->width; i++) {
93+
image->pixels[i] = calloc(image->height, sizeof(bool));
94+
// check for malloc fail
95+
if(image->pixels[i] == NULL) {
96+
// we need to free() all previous rows
97+
for(size_t j = i; j > 0; j--) {
98+
free(image->pixels[j]);
99+
}
100+
result.location = DEBUG;
101+
result.diagnostic = MALLOC_REFUSED;
102+
return result;
103+
}
91104
}
92105
// set 'current point' co-ordinate
93106
co_ord_t current = {
@@ -106,7 +119,7 @@ render_spiral(spiral_t spiral) {
106119
// skip the second pixel of the first line
107120
if(!((i == 0) && (j == 1))) {
108121
// flip the y-axis otherwise they appear vertically mirrored
109-
output.pixels[x_pos][output.height - 1 - y_pos] = true;
122+
image->pixels[x_pos][image->height - 1 - y_pos] = true;
110123
}
111124
if(j != (spiral.lines[i].length * 2)) {
112125
// if we're not on the last line, advance the marker along
@@ -115,7 +128,9 @@ render_spiral(spiral_t spiral) {
115128
}
116129
}
117130
}
118-
return output;
131+
// status ok
132+
result.diagnostic = OPERATION_OK;
133+
return result;
119134
}
120135

121136
#ifdef __cplusplus

0 commit comments

Comments
 (0)