curvedraw

view src/curvefile.cc @ 11:099fd7adb900

curve parser works
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 19 Dec 2015 22:39:18 +0200
parents 95fada20c638
children 84a647283237
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(fp, "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 std::list<Curve*> load_curves(const char *fname)
57 {
58 std::list<Curve*> res;
59 FILE *fp = fopen(fname, "r");
60 if(!fp) return res;
62 res = load_curves(fp);
63 fclose(fp);
64 return res;
65 }
67 static std::string next_token(FILE *fp)
68 {
69 std::string s;
70 int c;
71 while((c = fgetc(fp)) != -1) {
72 if(!isspace(c)) {
73 ungetc(c, fp);
74 break;
75 }
76 }
78 if(feof(fp)) return s;
79 while((c = fgetc(fp)) != -1) {
80 if(isspace(c)) {
81 ungetc(c, fp);
82 break;
83 }
84 s.push_back(c);
85 }
87 printf("TOKEN: \"%s\"\n", s.c_str());
88 return s;
89 }
91 static bool expect_str(FILE *fp, const char *s)
92 {
93 std::string tok = next_token(fp);
94 if(tok != std::string(s)) {
95 if(tok.empty() && feof(fp)) {
96 fprintf(stderr, "expected: %s\n", s);
97 }
98 return false;
99 }
100 return true;
101 }
103 static bool expect_float(FILE *fp, float *ret)
104 {
105 std::string tok = next_token(fp);
106 const char *cs = tok.c_str();
107 char *endp;
108 *ret = strtod(cs, &endp);
109 if(endp != cs + tok.length()) {
110 if(!(tok.empty() && feof(fp))) {
111 fprintf(stderr, "number expected\n");
112 }
113 return false;
114 }
115 return true;
116 }
118 static bool expect_int(FILE *fp, int *ret)
119 {
120 std::string tok = next_token(fp);
121 const char *cs = tok.c_str();
122 char *endp;
123 *ret = strtol(cs, &endp, 0);
124 if(endp != cs + tok.length()) {
125 if(!(tok.empty() && feof(fp))) {
126 fprintf(stderr, "integer expected\n");
127 }
128 return false;
129 }
130 return true;
131 }
133 static Curve *curve_block(FILE *fp)
134 {
135 if(!expect_str(fp, "curve") || !expect_str(fp, "{")) {
136 return 0;
137 }
139 Curve *curve = new Curve;
140 int cpcount = -1;
141 std::string tok;
142 while(!(tok = next_token(fp)).empty() && tok != "}") {
143 if(tok == "cpcount") {
144 if(cpcount != -1 || !expect_int(fp, &cpcount) || cpcount <= 0) {
145 goto err;
146 }
147 } else if(tok == "type") {
148 tok = next_token(fp);
149 if(tok == "polyline") {
150 curve->set_type(CURVE_LINEAR);
151 } else if(tok == "hermite") {
152 curve->set_type(CURVE_HERMITE);
153 } else if(tok == "bspline") {
154 curve->set_type(CURVE_BSPLINE);
155 } else {
156 goto err;
157 }
158 } else {
159 if(tok != "cp") {
160 goto err;
161 }
162 Vector3 cp;
163 for(int i=0; i<3; i++) {
164 if(!expect_float(fp, &cp[i])) {
165 goto err;
166 }
167 }
168 curve->add_point(Vector2(cp.x, cp.y), cp.z);
169 }
170 }
172 if(curve->size() != cpcount) {
173 fprintf(stderr, "warning: curve cpcount was %d, but read %d control points\n", cpcount, curve->size());
174 }
176 return curve;
177 err:
178 fprintf(stderr, "failed to parse curve block\n");
179 delete curve;
180 return 0;
181 }
183 std::list<Curve*> load_curves(FILE *fp)
184 {
185 std::list<Curve*> curves;
186 if(!expect_str(fp, "GCURVES")) {
187 fprintf(stderr, "load_curves: failed to load, invalid file format\n");
188 return curves;
189 }
191 Curve *curve;
192 while((curve = curve_block(fp))) {
193 curves.push_back(curve);
194 }
196 int ncurves = (int)curves.size();
197 if(!feof(fp)) {
198 std::list<Curve*>::iterator it = curves.begin();
199 while(it != curves.end()) {
200 delete *it++;
201 }
202 return curves;
203 }
205 return curves;
206 }