curvedraw

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