diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/fractal_render.c | 130 | ||||
| -rw-r--r-- | src/fractal_render.h | 5 | ||||
| -rw-r--r-- | src/fractals.c | 14 | ||||
| -rw-r--r-- | src/grids.c | 19 | ||||
| -rw-r--r-- | src/grids.h | 2 |
5 files changed, 150 insertions, 20 deletions
diff --git a/src/fractal_render.c b/src/fractal_render.c index bac8202..b9ffa09 100644 --- a/src/fractal_render.c +++ b/src/fractal_render.c @@ -1,18 +1,134 @@ #include <stdio.h> +#include <stdlib.h> +#include <getopt.h> +#include <string.h> +#include <setjmp.h> + #include "grids.h" #include "precision.h" #include "fractal_render.h" +void print_usage(FILE* file, const char* program_name) { + fprintf(file, "Usage: %s -i input.grid [-r renderer] [-o output.ext]\n", program_name); +} + +void print_help(){ + printf("Options:\n" + " -i, --input <input grid> the grid to be rendered, if the file name is '-' reads from stdin\n" + " -r, --renderer <renderer> the renderer to use, defaults to the text renderer\n" + " renderers: txt, png (TODO), gif (TODO, with additional features)\n" + " -o, --output <output file> the file to output the result of rendering, if not given defaults to output.<EXT>\n" + " where <EXT> is the renderer used\n" + " -v, --verbose verbose output\n" + " -h, --help prints this help and exits\n" + ); +} + +jmp_buf error_buffer; + +/* + * Error logger that causes used file streams to be closed + */ +void error_exit(const char* message, const char* issue) { + if(issue){ + fprintf(stderr, "%s: %s\n", message, issue); + } + else { + fprintf(stderr, "%s\n", message); + } + longjmp(error_buffer, 1); +} + +/* + * Cleanup io files and a grid + */ +void cleanup(FILE* output_file, FILE* input_file, grid_t* grid) { + if(output_file) fclose(output_file); + // closing stdin is not recommended, can supposedly cause odd behvaior + if(input_file && input_file != stdin) fclose(input_file); + if(grid) free_grid(grid); +} + + int main(const int argc, char* argv[]){ - char* input_file = "test.grid"; - FILE* file = fopen(input_file, "rb"); - grid_t* grid = read_grid(file); - fclose(file); + char* input_filename = "fractal.grid"; + char* output_filename = "fractal.txt"; + renderer_func renderer = print_grid; + bool verbose = false; + + static struct option long_options[] = { + {"input", required_argument, NULL, 'i'}, + {"renderer", required_argument, NULL, 'r'}, + {"output", required_argument, NULL, 'o'}, + {"verbose", no_argument, NULL, 'v'}, + {"help", no_argument, NULL, 'h'}, + {0, 0, 0, 0} + }; + + int opt; + while((opt = getopt_long(argc, argv, "i:r:o:vh", long_options, NULL)) != -1){ + switch(opt){ + case 'i': + input_filename = optarg; + break; + case 'r': + //TODO: update with other renderers + renderer = print_grid; + break; + case 'o': + output_filename = optarg; + break; + case 'v': + verbose = true; + break; + case 'h': + print_usage(stdout, argv[0]); + print_help(); + return 0; + default: + print_usage(stderr, argv[0]); + fprintf(stderr, "See --help for more info\n"); + return 1; + + } + } + //TODO: logic to set output_filename if o flag is not used + + FILE* input_file = NULL; + FILE* output_file = NULL; + grid_t* grid = NULL; + + if (setjmp(error_buffer) != 0) { + cleanup(output_file, input_file, grid); + exit(EXIT_FAILURE); + } + + if(strcmp(output_filename, "-") == 0){ + output_file = stdout; + } + else { + output_file = fopen(output_filename, "wb"); + if (!output_file) { error_exit("Error opening output file", output_filename); } + } + + if(strcmp(input_filename, "-") == 0){ + grid = read_grid(stdin); + if (!grid) { error_exit("Error reading from stdin", NULL); } + } + else { + input_file = fopen(input_filename, "rb"); + if (!input_file) { error_exit("Error opening input file", input_filename); } + grid = read_grid(input_file); + if (!grid) { error_exit("Error reading from file", input_filename); } + } + + if(verbose){ + print_grid_info(grid); + } - if(!grid) return 1; + renderer(output_file, grid); - print_grid_info(grid); + cleanup(output_file, input_file, grid); - free_grid(grid); return 0; } diff --git a/src/fractal_render.h b/src/fractal_render.h index 6f70f09..a23acad 100644 --- a/src/fractal_render.h +++ b/src/fractal_render.h @@ -1 +1,6 @@ #pragma once + +#include <stdio.h> +#include "grids.h" + +typedef void (*renderer_func)(FILE*, const grid_t*); diff --git a/src/fractals.c b/src/fractals.c index 4d8967e..395ccdb 100644 --- a/src/fractals.c +++ b/src/fractals.c @@ -193,17 +193,21 @@ int main(const int argc, char *argv[]) { } //use "safer" versions of c string functions - if(strncmp(output_filename, "-", 1) && strnlen(output_filename, 16) == 1){ + //likely aren't necessary unless a user can pass non-null terminated strings as arguments, but that would likely break something up in getopt + if(output_filename[0] == '-' && strnlen(output_filename, 16) == 1){ if(write_grid(stdout, grid) == GRID_WRITE_ERROR){ - fprintf(stderr, "Error writing occured while writting to file %s\n", output_filename); + fprintf(stderr, "Error occured while writting to file %s\n", output_filename); } } else { FILE* file = fopen(output_filename, "wb"); - if(write_grid(file, grid) == GRID_WRITE_ERROR){ - fprintf(stderr, "Error writing occured while writting to file %s\n", output_filename); + if(!file){ + perror("Error occured while trying to write"); } - fclose(file); + else if(write_grid(file, grid) == GRID_WRITE_ERROR){ + fprintf(stderr, "Error occured while writting to file %s\n", output_filename); + } + fclose(file); } free(params); diff --git a/src/grids.c b/src/grids.c index 2bb87e6..354189b 100644 --- a/src/grids.c +++ b/src/grids.c @@ -233,7 +233,7 @@ void print_grid_info(const grid_t* grid){ /* * Attempts an ASCII print of the grid */ -void print_grid(const grid_t* grid){ +void print_grid(FILE* file, const grid_t* grid){ const size_t size = grid->size; const size_t x_res = grid->x; const size_t iterations = grid->max_iterations; @@ -241,15 +241,18 @@ void print_grid(const grid_t* grid){ //TODO: set values in output buffer rather than multiple printf calls // the buffer needs to be larger to hold newlines - // char* output_buffer = malloc(size); - // if(!output_buffer){ - // fprintf(stderr, "Failed to allocate output buffer for %zu points\n"); - // return; - // } + char* output_buffer = malloc(size + grid->y-1); + if(!output_buffer){ + fprintf(stderr, "Failed to allocate output buffer for %zu points\n", size); + return; + } + + setvbuf(file, output_buffer, _IOFBF, size + grid->y - 1); const char point_types[] = { ' ', '.', '*', '%', '#'}; size_t bin_width = iterations/3; size_t last_bin = iterations - bin_width; + char* buffer_ptr = output_buffer; char point; for(size_t i = 0; i < size; i++){ @@ -269,8 +272,10 @@ void print_grid(const grid_t* grid){ else { point = point_types[2]; } - printf("%c%s", point, (i % x_res == x_res - 1) ? "\n" : ""); + fprintf(file ,"%c%s", point, (i % x_res == x_res - 1) ? "\n" : ""); } + fflush(file); + free(output_buffer); } /* diff --git a/src/grids.h b/src/grids.h index b823c91..293ceb5 100644 --- a/src/grids.h +++ b/src/grids.h @@ -44,6 +44,6 @@ CBASE complex grid_to_complex(const grid_t* grid, const size_t index); void zoom_grid(grid_t* grid, const CBASE magnification); void print_grid_info(const grid_t* grid); -void print_grid(const grid_t* grid); +void print_grid(FILE* file, const grid_t* grid); int write_grid(FILE* file, const grid_t* grid); grid_t* read_grid(FILE* file); |
