//parse a config file and generate a Renderer Renderer* ConfigParser::parse(std::string filename){ std::cout << "ConfigParser::parse config file... " << filename <<" \n"; struct basicxmlnode * rootNode = NULL; //open file FILE * fp = fopen(filename.c_str(), "rt"); if (!fp) { std::cerr << "ConfigParser - Error: Failed opening file " << filename << "\n"; return NULL; } rootNode = readbasicxmlnode(fp); fclose(fp); if (!rootNode) { std::cerr << "ConfigParser - Error: Failed reading file " << filename << ". Maybe an XML syntax error?\n"; return NULL; } //create renderer Renderer* renderer = new Renderer(); //read renderer properties if (!addRendererProperties(rootNode, renderer)) { std::cerr << "ConfigParser - Error: Failed reading renderer properties in " << filename << "\n"; deletebasicxmlnode(rootNode); delete(renderer); return NULL; } //read sampler struct basicxmlnode * samplerNode = getchildnodebyname(rootNode, "Sampler"); if (!addSampler(samplerNode, renderer)) { std::cerr << "ConfigParser - Error: Failed reading sampler description in " << filename << "\n"; deletebasicxmlnode(rootNode); delete(renderer); return NULL; } //read shader struct basicxmlnode * shaderNode = getchildnodebyname(rootNode, "Shader"); if (!addShader(shaderNode, renderer)) { std::cerr << "ConfigParser - Error: Failed reading shader description in " << filename << "\n"; deletebasicxmlnode(rootNode); delete(renderer); return NULL; } //free xml memory deletebasicxmlnode(rootNode); std::cout << "[done]\n\n"; return renderer; }
void Population::LoadConfigFile(char* iniFile) { // Loads the data file population information _rootConfig = NULL; FILE * fp = fopen(iniFile, "rt"); if (!fp) { throw("open failed"); } _rootConfig = readbasicxmlnode(fp); fclose(fp); if (!_rootConfig) { throw("read failed"); } }
//parse a scene description file and generate a Scene Scene* SceneParser::parse(const char* filename){ std::cout << "SceneParser::parse parses scene... " << filename <<" \n"; struct basicxmlnode * rootNode = NULL; //open file FILE * fp = fopen(filename, "rt"); if (!fp) { std::cerr << "SceneParser - Error: Failed opening file " << filename << "\n"; return NULL; } std::string filenameString = std::string(filename); size_t index = filenameString.find_last_of("/"); if (index == std::string::npos) { index = filenameString.find_last_of("\\"); } if (index == std::string::npos) { directory = ""; } else { directory = filenameString.substr(0,index+1); } //read xml tree rootNode = readbasicxmlnode(fp); fclose(fp); if (!rootNode) { std::cerr << "SceneParser - Error: Failed reading file " << filename << ". Maybe an XML syntax error?\n"; return NULL; } //construct scene Scene* scene = new Scene(); //read scene properties if (!addSceneProperties(rootNode, scene)) { std::cerr << "SceneParser - Error: Failed to read Scene Properties in " << filename << "\n"; deletebasicxmlnode(rootNode); delete(scene); return NULL; } //read camera struct basicxmlnode * cameraNode = getchildnodebyname(rootNode, "Camera"); if (!addCamera(cameraNode, scene)) { std::cerr << "SceneParser - Error: Failed reading camera description in " << filename << "\n"; deletebasicxmlnode(rootNode); delete(scene); return NULL; } //read lights struct basicxmlnode * lightsNode = getchildnodebyname(rootNode, "Lights"); if (!lightsNode) { std::cout << "SceneParser - Warning: No Lights specified in " << filename << "\n"; } else if (!lightsNode->children[0]) { std::cout << "SceneParser - Warning: No Lights specified in " << filename << "\n"; } else { for(int lightsIndex = 0; lightsNode->children[lightsIndex]; lightsIndex++) { if(!addLight(lightsNode->children[lightsIndex], scene)) { std::cerr << "SceneParser - Error: Failed reading light description in " << filename << "\n"; deletebasicxmlnode(rootNode); delete(scene); return NULL; } } } //read materials struct basicxmlnode * materialsNode = getchildnodebyname(rootNode, "Materials"); if (!materialsNode) { std::cout << "SceneParser - No global Materials specified in " << filename << "\n"; } else if (!materialsNode->children[0]) { std::cout << "SceneParser - Empty Materials node in " << filename << "\n"; } else { for(int materialsIndex = 0; materialsNode->children[materialsIndex]; materialsIndex++) { if(!addGlobalMaterial(materialsNode->children[materialsIndex], scene)) { std::cerr << "SceneParser - Error: Failed reading global material description in " << filename << "\n"; deletebasicxmlnode(rootNode); delete(scene); return NULL; } } } //read textures struct basicxmlnode* texturesNode = getchildnodebyname(rootNode, "Textures"); if (!texturesNode) { std::cout << "SceneParser - No global Textures specified in " << filename << "\n"; } else if (!texturesNode->children[0]) { std::cout << "SceneParser - Empty Textures node in " << filename << "\n"; } else { for(int texturesIndex = 0; texturesNode->children[texturesIndex]; texturesIndex++) { if(!addGlobalTexture(texturesNode->children[texturesIndex], scene)) { std::cerr << "SceneParser - Error: Failed reading global texture description in " << filename << "\n"; deletebasicxmlnode(rootNode); delete(scene); return NULL; } } } //read elements struct basicxmlnode * elementsNode = getchildnodebyname(rootNode, "Elements"); if (!elementsNode) { std::cout << "SceneParser - Warning: No Elements specified in " << filename << "\n"; } else if (!elementsNode->children[0]) { std::cout << "SceneParser - Warning: No Elements specified in " << filename << "\n"; } for(int elementsIndex = 0; elementsNode->children[elementsIndex]; elementsIndex++) { if(!addElement(elementsNode->children[elementsIndex], scene)) { std::cerr << "SceneParser - Error: Failed reading element description in " << filename << "\n"; deletebasicxmlnode(rootNode); delete(scene); return NULL; } } //free xml memory deletebasicxmlnode(rootNode); std::cout << "[done]\n\n"; return scene; }
/* readbasicxmlnode: reads simple XML file */ struct basicxmlnode *readbasicxmlnode( FILE * fpi ) { int bufinc=500, textinc=50, childinc=50; /* tuning */ char * buf=0; int nbuf=0; char * ibuf=0, * buftmp, * wspos, * ps, * pe, * pe2; int phase=0, ch=0, err=0, ii=0, ia, natts, * nodeitmp; int itex=0, ntex=textinc, ichi=0, nchi=childinc, nest=0; typedef /*struct*/ basicxmlnode nodetype; nodetype * node, * child, * * nodetmp; if (!err && !fpi) err=1; /* bad arg */ /* get chars between < and >; strip most whitespace */ while (1) { int isws=0, issl=0, islt=0, isgt=0, iseq=0, isqu=0; int isqs=0, isex=0, isda=0, issi=0, isls=0, isrs=0; int isn1=0, isn2=0; if ((ibuf-buf+5) > nbuf) { /* realloc buf */ nbuf += bufinc; buftmp = new char[nbuf]; /*(char*)malloc(so_c*nbuf);*/ if (!buftmp) { err=2; break; /* out of memory */ } if (buf) { ii = ibuf-buf; strncpy(buftmp, buf, ii); delete [] buf; /*free(buf);*/ } buf = buftmp; ibuf = buf + ii; } if (phase != 100) ch = fgetc(fpi); if (err || feof(fpi) || (phase == 100)) break; /* analyze char */ /* /<>="?!-'12*/ if ((ch == ' ') || ((ch > 8) && (ch < 14))) isws = 1; if (ch == '/') issl = 1; if (ch == '<') islt = 1; if (ch == '>') isgt = 1; if (ch == '=') iseq = 1; if (ch == '"') isqu = 1; if (ch == '?') isqs = 1; if (ch == '!') isex = 1; if (ch == '-') isda = 1; if (ch == '[') isls = 1; if (ch == ']') isrs = 1; if (ch == '\'') issi = 1; if ((ch >= 'a') && (ch <= 'z')) isn1 = 1; if ((ch >= 'A') && (ch <= 'Z')) isn1 = 1; if (ch == '_') isn1 = 1; if (isn1 || isda || (ch == '.')) isn2 = 1; if ((ch >= '0') && (ch <= '9')) isn2 = 1; /* err=3, bad xml file (parsing error) */ switch (phase) { case 0: /* eat whitespace before < */ if (isws) { } /* */ else if (islt) { ++phase; *ibuf=ch; ++ibuf; } /*<*/ else { err=3; } /**/ /*/>="?!-'t1*/ break; case 1: /* handle the first char after < */ if (issl) { phase=10; *ibuf=ch; ++ibuf; } /*</*/ else if (isqs) { phase=14; --ibuf; } /*<?*/ else if (isex) { phase=15; --ibuf; } /*<!*/ else if (isn1) { ++phase; *ibuf=ch; ++ibuf; } /*<t*/ else { err=3; } /*<*/ /* <>="-'1*/ break; case 2: /* store tag name and a single space after it */ if (isws) { ++phase; *ibuf = ' '; ++ibuf; } /*<t */ else if (issl) { phase=13; strncpy(ibuf," /",2); ibuf+=2; } /*<t/*/ else if (isgt) { phase=100; strncpy(ibuf," >",2); ibuf+=2; } /*<t>*/ else if (isn2) { *ibuf=ch; ++ibuf; } /*<t*/ /*-1*/ else { err=3; } /*<t*/ /*<="?!'*/ break; case 3: /* eat whitespace after tag name */ if (isws) { } /*<tag */ else if (issl) { phase=13; *ibuf=ch; ++ibuf; } /*<tag /*/ else if (isgt) { phase=100; *ibuf=ch; ++ibuf; } /*<tag >*/ else if (isn1) { ++phase; *ibuf=ch; ++ibuf; } /*<tag t*/ else { err=3; } /*<tag */ /*<="?!-'1*/ break; case 4: /* store attribute name */ if (isws) { ++phase; } /*<tag a */ else if (iseq) { phase=6; *ibuf=ch; ++ibuf; } /*<tag a=*/ else if (isn2) { *ibuf=ch; ++ibuf; } /*<tag a*/ /*-t1*/ else { err=3; } /*<tag a*/ /*/<>"?!'t*/ break; case 5: /* eat whitespace after attribute name */ if (isws) { } /*<tag attr */ else if (iseq) { ++phase; *ibuf=ch; ++ibuf; } /*<tag attr =*/ else { err=3; } /*<tag attr */ /*/<>"?!-'t1*/ break; case 6: /* eat whitespace after = */ if (isws) { } /*<tag attr= */ else if (isqu) { ++phase; *ibuf=ch; ++ibuf; } /*<tag attr="*/ else if (issi) { phase=8; *ibuf=ch; ++ibuf; } /*<tag attr='*/ else { err=3; } /*<tag attr=*/ /*/<>=?!-t1*/ break; case 7: /* store the attribute value ("value") */ if (isws) { *ibuf=' '; ++ibuf; } /*tag attr=" */ else if (islt) { err=3; } /*<tag attr="<*/ else if (isqu) { phase=9; *ibuf=ch; ++ibuf; } /*<tag attr=""*/ else { *ibuf=ch; ++ibuf; } /*tag attr="*/ /*/>=?!-'t1*/ break; case 8: /* store the attribute value ('value') */ if (isws) { *ibuf=' '; ++ibuf; } /*<tag attr=' */ else if (islt) { err=3; } /*<tag attr='<*/ else if (issi) { ++phase; *ibuf=ch; ++ibuf; } /*<tag attr=''*/ else { *ibuf=ch; ++ibuf; } /*tag attr='*/ /*/>="?!-t1*/ break; case 9: /* eat whitespace after attribute value */ if (isws) { phase=3; *ibuf=' '; ++ibuf; } /*<tag attr="value" */ else if (issl) { phase=13; strncpy(ibuf," /",2); ibuf+=2; } /*..."/*/ else if (isgt) { phase=100; strncpy(ibuf," >",2); ibuf+=2; } /*...">*/ else { err=3; } /*tag attr="value"*/ /*<="?!-'t1*/ break; case 10: /* handle the first char after </ */ if (isn1) { ++phase; *ibuf=ch; ++ibuf; } /*</t*/ else { err=3; } /*</*/ /* /<>="?!-'1*/ break; case 11: /* store tag name and a single space after it */ if (isws) { ++phase; *ibuf=' '; ++ibuf; } /*</t */ else if (isgt) { phase=100; strncpy(ibuf," >",2); ibuf+=2; } /*</t>*/ else if (isn2) { *ibuf=ch; ++ibuf; } /*</t*/ /*-t*/ else { err=3; } /*</t*/ /*/<="?!'*/ break; case 12: /* eat whitespace before > */ if (isws) { } /*</tag */ else if (isgt) { phase=100; *ibuf=ch; ++ibuf; } /*</tag >*/ else { err=3; } /*</tag */ /*/<="?!-'t1*/ break; case 13: /* ensure final > */ if (isgt) { phase=100; *ibuf=ch; ++ibuf; } /*<tag />*/ else { err=3; } /*<tag /*/ /* /<="?!-'t1*/ break; case 14: /* skip tag (probably <? tag) */ if (isgt) { if (nest < 1) nest=phase=0; } /*<?>*/ else if (isls) { ++nest; } /*<?[*/ else if (isrs) { --nest; } /*<?[*/ else { } /*<?*/ /* /<="?!-'t1*/ break; case 15: /* find first - (<! tag) */ if (isgt) { phase=0; } /*<!>*/ else if (isda) { ++phase; } /*<!-*/ else if (isls) { ++nest; phase=14; } /*<![*/ else { phase=14; } /*<!*/ /* /<="?!'t1*/ break; case 16: /* find second - (<!- tag) */ if (isgt) { phase=0; } /*<!->*/ else if (isda) { ++phase; } /*<!--*/ else { phase=14; } /*<!-*/ /* /<="?!'t1*/ break; case 17: /* skip comment */ if (isda) { ++phase; } /*-*/ else { } /**/ /* /<>="?!'t1*/ break; case 18: /* find second - in --> */ if (isda) { ++phase; } /*--*/ else { phase=17; } /*-*/ /* /<>="?!'t1*/ break; case 19: /* find > in --> */ if (isgt) { phase=0; } /*-->*/ else { err=3; } /*--*/ /* /<="?!-'t1*/ break; }; if (err) break; } if (!err && (phase != 100)) { err=4; /* incomplete xml file */ } if (!err) *ibuf = 0; /* buf is now in one of these formats: */ /* <tag > or </tag > or <tag /> or */ /* <tag attr="value" ... attr="value" > or */ /* <tag attr="value" ... attr="value" /> */ /* allocate memory for a node */ node = new nodetype; /*(nodetype*)malloc(so_n);*/ if (node) { node->tag = node->text = 0; node->attrs = node->values = 0; node->children = 0; node->childreni = 0; } if (!err) { if (!node) { err=5; /* out of memory */ } else { memset(node, 0, sizeof(node)); } } /* put tag name into node */ if (!err) { wspos = strchr(buf, ' '); node->tag = new char[wspos-buf]; /*(char*)malloc(so_c*(wspos-buf));*/ if (!node->tag) err=6; /* out of memory */ } if (!err) { strncpy(node->tag, buf+1, wspos-buf-1); node->tag[wspos-buf-1] = 0; if (buf[1] == '/') { /* end tag (not err) */ delete [] buf; /*free(buf);*/ return node; } /* estimate # of attrs and values (maybe too much) */ pe = strstr(wspos, "\" "); pe2 = strstr(wspos, "' "); for (natts=0; pe || pe2; ++natts) { if (!pe || (pe2 && (pe2 < pe))) pe = pe2; pe2 = strstr(pe+1, "' "); pe = strstr(pe+1, "\" "); } node->attrs = new char *[natts+1]; /*(char**)malloc(so_cp*(natts+1));*/ node->values = new char *[natts+1]; /*(char**)malloc(so_cp*(natts+1));*/ if (!node->attrs||!node->values) { if (node->attrs) delete [] node->attrs; /*free(node->attrs);*/ if (node->values) delete [] node->values; /*free(node->values);*/ node->attrs=node->values=0; err=7; /* out of memory */ } } /* put attrs and values into node (and recount #) */ if (!err) { ps = wspos+1; pe = strstr(wspos, "=\""); pe2 = strstr(wspos, "='"); } for (natts=0, ia=0; !err && (pe||pe2); ++ia, ++natts) { if (!pe || (pe2 && (pe2 < pe))) pe = pe2; node->attrs[ia] = new char[pe-ps+1]; /*(char*)malloc(so_c*(pe-ps+1));*/ if (!node->attrs[ia]) { node->values[ia]=0; err=8; break; /* out of memory */ } strncpy(node->attrs[ia], ps, pe-ps); node->attrs[ia][pe-ps] = 0; node->attrs[ia+1] = 0; ps = pe + 2; if (pe == pe2) pe = strstr(ps, "' "); else pe = strstr(ps, "\" "); node->values[ia] = new char[pe-ps+1]; /*(char*)malloc(so_c*(pe-ps+1));*/ if (!node->values[ia]) { err=9; break; } /* out of memory */ strncpy(node->values[ia], ps, pe-ps); node->values[ia][pe-ps] = 0; node->values[ia+1] = 0; ps = pe + 2; pe2 = strstr(ps, "='"); pe = strstr(ps, "=\""); } if (!err) { node->attrs[natts] = node->values[natts] = 0; /* no children for self-contained tag, save memory */ if (buf[strlen(buf)-2] == '/') { ntex = 1; nchi = 1; } /* no body or children yet */ node->text = new char[ntex]; /*(char*)malloc(so_c*ntex);*/ node->children = new nodetype *[nchi]; /*(nodetype**)malloc(so_np*nchi);*/ node->childreni = new int [nchi]; /*(int*)malloc(so_i*nchi);*/ if (!node->text || !node->children || !node->childreni) { err=10; /* out of memory */ } else { node->text[0] = 0; node->children[0] = 0; node->childreni[0] = 0; } } if (!err) { if (ntex == 1) { /* end tag, no children (not err) */ delete [] buf; /*free(buf);*/ return node; } } /* read child tags */ for (ichi=0; !err; ++ichi) { /* add more text to node (between child tags) */ for (ch=fgetc(fpi); ch != '<'; ch=fgetc(fpi)) { if (feof(fpi)) { err=11; /* incomplete xml file */ break; } if ((itex+2) == ntex) { /* realloc text */ ntex += textinc; buftmp = new char[ntex]; /*(char*)malloc(so_c*ntex);*/ if (!buftmp) { err=12; break; } /* out of memory */ strncpy(buftmp, node->text, itex); delete [] node->text; /*free(node->text);*/ node->text = buftmp; } node->text[itex++] = ch; } if (err) continue; node->text[itex] = 0; ungetc(ch, fpi); /* oops, put back next tag's "<" */ child = readbasicxmlnode(fpi); if (child) { if (child->tag[0] == '/') { if (strcmp(child->tag+1, node->tag)) { err=13; /* end tag mismatch */ } delete [] child->tag; /*free(child->tag);*/ delete child; /*free(child);*/ child=0; } } else if (!err) { err=14; /* bad child */ } if (err || !child) break; node->children[ichi] = child; node->childreni[ichi] = itex; if ((ichi+2) == nchi) { /* realloc child tags array */ nchi += childinc; nodetmp = new nodetype *[nchi]; /*(nodetype**)malloc(so_np*nchi);*/ if (!nodetmp) { err=15; continue; } /* out of memory */ nodeitmp = new int [nchi]; /*(int*)malloc(so_i*nchi);*/ if (!nodeitmp) { delete [] nodetmp; /*free(nodetmp);*/ nodetmp=0; err=16; continue; /* out of memory */ } for (ii=0; ii <= ichi; ++ii) { /* copy */ nodetmp[ii] = node->children[ii]; nodeitmp[ii] = node->childreni[ii]; } delete [] node->children; /*free(node->children);*/ delete [] node->childreni; /*free(node->childreni);*/ node->children = nodetmp; node->childreni = nodeitmp; } } if (node) { if (node->children) { node->children[ichi] = 0; node->childreni[ichi] = 0; if (err) { /* delete complete node */ deletebasicxmlnode(node); node = 0; } } else { /* delete partial node */ if (node->tag) delete [] node->tag; /*free(node->tag);*/ if (node->text) delete [] node->text; /*free(node->text);*/ if (node->attrs) { for (ii=0; node->attrs[ii]; ++ii) { delete [] node->attrs[ii]; /*free(node->attrs[ii]);*/ } } if (node->values) { for (ii=0; node->values[ii]; ++ii) { delete [] node->values[ii]; /*free(node->values[ii]);*/ } } if (node->attrs) delete node->attrs; /*free(node->attrs);*/ if (node->values) delete node->values; /*free(node->values);*/ delete node; /*free(node);*/ node = 0; } } if (buf) delete [] buf; /*free(buf);*/ return node; /* whew! return complete node */ }