curvedraw

view src/curvefile.cc @ 8:8bf96e11ed1f

curves file format parsing (untested)
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 19 Dec 2015 08:00:09 +0200
parents 6e980fddbf3b
children 95fada20c638
line source
1 #include <stdlib.h>
2 #include <ctype.h>
3 #include <string>
4 #include "curvefile.h"
6 static bool save_curve(FILE *fp, const Curve *curve);
8 bool save_curves(const char *fname, const Curve * const *curves, int count)
9 {
10 FILE *fp = fopen(fname, "wb");
11 if(!fp) return false;
13 bool res = save_curves(fp, curves, count);
14 fclose(fp);
15 return res;
16 }
18 bool save_curves(FILE *fp, const Curve * const *curves, int count)
19 {
20 fprintf(stderr, "GCURVES\n");
22 for(int i=0; i<count; i++) {
23 if(!save_curve(fp, curves[i])) {
24 return false;
25 }
26 }
27 return true;
28 }
30 static const char *curve_type_str(CurveType type)
31 {
32 switch(type) {
33 case CURVE_LINEAR:
34 return "polyline";
35 case CURVE_HERMITE:
36 return "hermite";
37 case CURVE_BSPLINE:
38 return "bspline";
39 }
40 abort();
41 }
43 static bool save_curve(FILE *fp, const Curve *curve)
44 {
45 fprintf(fp, "curve {\n");
46 fprintf(fp, " type %s\n", curve_type_str(curve->get_type()));
47 fprintf(fp, " cpcount %d\n", curve->size());
48 for(int i=0; i<curve->size(); i++) {
49 Vector3 cp = curve->get_homo_point(i);
50 fprintf(fp, " cp %g %g %g\n", cp.x, cp.y, cp.z);
51 }
52 fprintf(fp, "}\n");
53 return true;
54 }
56 Curve **load_curves(const char *fname, int *countret)
57 {
58 FILE *fp = fopen(fname, "r");
59 if(!fp) return false;
61 Curve **res = load_curves(fp, countret);
62 fclose(fp);
63 return res;
64 }
66 static std::string next_token(FILE *fp)
67 {
68 std::string s;
69 int c;
70 while((c = fgetc(fp)) != -1 && isspace(c)); // skip whitespace
71 if(feof(fp)) return s;
72 while((c = fgetc(fp)) != -1 && !isspace(c)) {
73 s.push_back(c);
74 }
75 return s;
76 }
78 static bool expect_str(FILE *fp, const char *s)
79 {
80 std::string tok = next_token(fp);
81 if(tok != std::string(s)) {
82 if(!(tok.empty() && feof(fp))) {
83 fprintf(stderr, "expected: %s\n", s);
84 }
85 return false;
86 }
87 return true;
88 }
90 static bool expect_float(FILE *fp, float *ret)
91 {
92 std::string tok = next_token(fp);
93 const char *cs = tok.c_str();
94 char *endp;
95 *ret = strtod(cs, &endp);
96 if(endp != cs + tok.length()) {
97 if(!(tok.empty() && feof(fp))) {
98 fprintf(stderr, "number expected\n");
99 }
100 return false;
101 }
102 return true;
103 }
105 static bool expect_int(FILE *fp, int *ret)
106 {
107 std::string tok = next_token(fp);
108 const char *cs = tok.c_str();
109 char *endp;
110 *ret = strtol(cs, &endp, 0);
111 if(endp != cs + tok.length()) {
112 if(!(tok.empty() && feof(fp))) {
113 fprintf(stderr, "integer expected\n");
114 }
115 return false;
116 }
117 return true;
118 }
120 static Curve *curve_block(FILE *fp)
121 {
122 if(!expect_str(fp, "curve") || !expect_str(fp, "{")) {
123 return 0;
124 }
126 Curve *curve = new Curve;
127 int cpcount = -1;
128 std::string tok;
129 while(!(tok = next_token(fp)).empty() && tok != "}") {
130 if(tok == "cpcount") {
131 if(cpcount != -1 || !expect_int(fp, &cpcount) || cpcount <= 0) {
132 goto err;
133 }
134 } else if(tok == "type") {
135 tok = next_token(fp);
136 if(tok == "polyline") {
137 curve->set_type(CURVE_LINEAR);
138 } else if(tok == "hermite") {
139 curve->set_type(CURVE_HERMITE);
140 } else if(tok == "bspline") {
141 curve->set_type(CURVE_BSPLINE);
142 } else {
143 goto err;
144 }
145 } else {
146 if(!expect_str(fp, "cp")) {
147 goto err;
148 }
149 Vector3 cp;
150 for(int i=0; i<3; i++) {
151 if(!expect_float(fp, &cp[i])) {
152 goto err;
153 }
154 }
155 curve->add_point(Vector2(cp.x, cp.y), cp.z);
156 }
157 }
159 if(curve->size() != cpcount) {
160 fprintf(stderr, "warning: curve cpcount was %d, but read %d control points\n", cpcount, curve->size());
161 }
163 return curve;
164 err:
165 fprintf(stderr, "failed to parse curve block\n");
166 delete curve;
167 return 0;
168 }
170 Curve **load_curves(FILE *fp, int *countret)
171 {
172 if(!expect_str(fp, "GCURVES")) {
173 fprintf(stderr, "load_curves: failed to load, invalid file format\n");
174 return 0;
175 }
177 std::vector<Curve*> curves;
178 Curve *curve;
180 while((curve = curve_block(fp))) {
181 curves.push_back(curve);
182 }
184 int ncurves = (int)curves.size();
185 if(!feof(fp)) {
186 for(int i=0; i<ncurves; i++) {
187 delete curves[i];
188 }
189 return 0;
190 }
192 Curve **carr = new Curve*[ncurves];
193 for(int i=0; i<ncurves; i++) {
194 carr[i] = curves[i];
195 }
196 *countret = ncurves;
197 return carr;
198 }