mightymandel v16

GPU-based Mandelbrot set explorer

parse.c
Go to the documentation of this file.
1 // mightymandel -- GPU-based Mandelbrot Set explorer
2 // Copyright (C) 2012,2013,2014,2015 Claude Heiland-Allen
3 // License GPL3+ http://www.gnu.org/licenses/gpl.html
4 
5 #include <assert.h>
6 #include <math.h>
7 #include <stdbool.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <mpfr.h>
12 
13 #include "parse.h"
14 #include "logging.h"
15 
16 #include "parse_gif.h"
17 #include "parse_kfr.h"
18 #include "parse_mdz_center.h"
19 #include "parse_mdz_corners.h"
20 #include "parse_mm.h"
21 #include "parse_png.h"
22 #include "parse_ppar_center.h"
23 #include "parse_ppar_corners.h"
24 #include "parse_ppm.h"
25 #include "parse_sft.h"
26 
27 bool radius_is_valid(const mpfr_t radius) {
28  return 0 < mpfr_sgn(radius) && mpfr_regular_p(radius);
29 }
30 
31 mpfr_prec_t precision_for_radius(const mpfr_t radius) {
32  assert(radius_is_valid(radius));
33  mpfr_t t;
34  mpfr_init2(t, 53);
35  mpfr_log2(t, radius, MPFR_RNDN);
36  mpfr_prec_t p = ceil(fmax(53, 16 - mpfr_get_d(t, MPFR_RNDN)));
37  mpfr_clear(t);
38  return p;
39 }
40 
41 char *load_file(const char *filename, int *length) {
42  assert(filename);
43  char *b = 0;
44  FILE *f = fopen(filename, "rb");
45  if (f) {
46  // calculate the size of the file
47  fseek(f, 0, SEEK_END);
48  *length = ftell(f);
49  fseek(f, 0, SEEK_SET);
50  // allocate a buffer with space for an additional null terminator character
51  b = (char *) malloc(*length + 1);
52  if (b) {
53  if (1 != fread(b, *length, 1, f)) {
54  free(b);
55  fclose(f);
56  return 0;
57  }
58  // add null terminator
59  b[*length] = 0;
60  }
61  fclose(f);
62  }
63  return b;
64 }
65 
66 char *parse_separator(char **source, int separator) {
67  if (! source) { return 0; }
68  if (! *source) { return 0; }
69  char *delim = strchr(*source, separator);
70  char *result = *source;
71  if (delim) {
72  *delim = 0;
73  *source = delim + 1;
74  } else {
75  *source = 0;
76  }
77  return result;
78 }
79 
80 char *parse_line(char **source) {
81  char *result = parse_separator(source, '\n');
82  char *cr = strrchr(result, '\r');
83  if (cr) {
84  *cr = 0;
85  }
86  // strip UTF-8 byte order marker if present
87  if (0 == strncmp("\xEF\xBB\xBF", result, 3)) {
88  result += 3;
89  }
90  return result;
91 }
92 
93 bool parse(const char *source, int length, mpfr_t cx, mpfr_t cy, mpfr_t cz) {
94 #define P(p) if (parse_##p(source, length, cx, cy, cz)) return true
95  // parse binary data first in case of mishaps
96  P(ppm);
97  P(png);
98  P(gif);
99  // now parse text formats
100  P(mm);
101  P(ppar_corners);
102  P(ppar_center);
103  P(kfr);
104  P(sft);
105  P(mdz_corners);
106  P(mdz_center);
107  return false;
108 #undef P
109 }
110 
111 bool load_parameter_file(const char *filename, mpfr_t cx, mpfr_t cy, mpfr_t cz) {
112  int length = 0;
113  char *b = load_file(filename, &length);
114  if (! b) {
115  log_message(LOG_ERROR, "failed to load file: %s\n", filename);
116  return false;
117  }
118  if (parse(b, length, cx, cy, cz)) {
119  log_message(LOG_NOTICE, "loaded parameter file: %s\n", filename);
120  free(b);
121  return true;
122  } else {
123  log_message(LOG_ERROR, "failed to parse file: %s\n", filename);
124  free(b);
125  return false;
126  }
127 }